diff --git a/addons/master/master.go b/addons/master/master.go
index f893e19bc3..242c7ee40b 100644
--- a/addons/master/master.go
+++ b/addons/master/master.go
@@ -66,7 +66,7 @@ type Trait struct {
type masterTrait struct {
trait.BaseTrait
Trait `property:",squash"`
- delegateDependencies []string `json:"-"`
+ delegateDependencies []string
}
// NewMasterTrait --.
@@ -105,7 +105,7 @@ func (t *masterTrait) Configure(e *trait.Environment) (bool, *trait.TraitConditi
}
}
if found {
- if t.IncludeDelegateDependencies == nil || *t.IncludeDelegateDependencies {
+ if ptr.Deref(t.IncludeDelegateDependencies, true) {
t.delegateDependencies = findAdditionalDependencies(e, meta)
}
}
@@ -117,28 +117,17 @@ func (t *masterTrait) Configure(e *trait.Environment) (bool, *trait.TraitConditi
return false, nil, err
}
if enabled {
+ t.Enabled = ptr.To(enabled)
if t.ResourceName == nil {
val := e.Integration.Name + "-lock"
t.ResourceName = &val
}
-
- if t.ResourceType == nil {
- t.ResourceType = ptr.To(leaseResourceType)
- }
-
- if t.LabelKey == nil {
- val := v1.IntegrationLabel
- t.LabelKey = &val
- }
-
if t.LabelValue == nil {
t.LabelValue = &e.Integration.Name
}
-
- return true, nil, nil
}
- return false, nil, nil
+ return enabled, nil, nil
}
func (t *masterTrait) Apply(e *trait.Environment) error {
@@ -172,49 +161,50 @@ func (t *masterTrait) setCustomizerConfiguration(e *trait.Environment) {
e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
v1.ConfigurationSpec{Type: "property", Value: "customizer.master.enabled=true"},
)
- if t.ResourceName != nil {
- resourceName := t.ResourceName
- e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
- v1.ConfigurationSpec{Type: "property", Value: "customizer.master.kubernetesResourceNames=" + *resourceName},
- )
- }
- if t.ResourceType != nil {
- e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
- v1.ConfigurationSpec{Type: "property", Value: "customizer.master.leaseResourceType" + *t.ResourceType},
- )
- }
- if t.LabelKey != nil {
- e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
- v1.ConfigurationSpec{Type: "property", Value: "customizer.master.labelKey=" + *t.LabelKey},
- )
- }
- if t.LabelValue != nil {
- e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
- v1.ConfigurationSpec{Type: "property", Value: "customizer.master.labelValue=" + *t.LabelValue},
- )
- }
+ e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
+ v1.ConfigurationSpec{Type: "property", Value: "customizer.master.kubernetesResourceNames=" + *t.ResourceName},
+ )
+ e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
+ v1.ConfigurationSpec{Type: "property", Value: "customizer.master.leaseResourceType" + t.getResourceKey()},
+ )
+ e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
+ v1.ConfigurationSpec{Type: "property", Value: "customizer.master.labelKey=" + t.getLabelKey()},
+ )
+ e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
+ v1.ConfigurationSpec{Type: "property", Value: "customizer.master.labelValue=" + *t.LabelValue},
+ )
}
func (t *masterTrait) setCatalogConfiguration(e *trait.Environment) {
if e.ApplicationProperties == nil {
e.ApplicationProperties = make(map[string]string)
}
- if t.ResourceName != nil {
- e.ApplicationProperties["camel.k.master.resourceName"] = *t.ResourceName
- }
- if t.ResourceType != nil {
- e.ApplicationProperties["camel.k.master.resourceType"] = *t.ResourceType
- }
- if t.LabelKey != nil && t.LabelValue != nil {
- e.ApplicationProperties["camel.k.master.labelKey"] = *t.LabelKey
- e.ApplicationProperties["camel.k.master.labelValue"] = *t.LabelValue
- }
+ e.ApplicationProperties["camel.k.master.resourceName"] = *t.ResourceName
+ e.ApplicationProperties["camel.k.master.resourceType"] = t.getResourceKey()
+ e.ApplicationProperties["camel.k.master.labelKey"] = t.getLabelKey()
+ e.ApplicationProperties["camel.k.master.labelValue"] = *t.LabelValue
for _, cp := range e.CamelCatalog.Runtime.Capabilities["master"].RuntimeProperties {
e.ApplicationProperties[trait.CapabilityPropertyKey(cp.Key, e.ApplicationProperties)] = cp.Value
}
}
+func (t *masterTrait) getResourceKey() string {
+ if t.ResourceType == nil {
+ return leaseResourceType
+ }
+
+ return *t.ResourceType
+}
+
+func (t *masterTrait) getLabelKey() string {
+ if t.LabelKey == nil {
+ return v1.IntegrationLabel
+ }
+
+ return *t.LabelKey
+}
+
func findAdditionalDependencies(e *trait.Environment, meta metadata.IntegrationMetadata) []string {
var dependencies []string
for _, endpoint := range meta.FromURIs {
diff --git a/addons/master/master_test.go b/addons/master/master_test.go
index c80b2abd6d..0754331b8f 100644
--- a/addons/master/master_test.go
+++ b/addons/master/master_test.go
@@ -21,6 +21,7 @@ import (
"testing"
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/trait"
"github.com/apache/camel-k/v2/pkg/util/camel"
"github.com/apache/camel-k/v2/pkg/util/kubernetes"
@@ -29,6 +30,7 @@ import (
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/ptr"
)
func TestMasterOn(t *testing.T) {
@@ -184,3 +186,79 @@ func TestMasterOff(t *testing.T) {
assert.Empty(t, conditions)
assert.False(t, configured)
}
+
+func TestMasterAuto(t *testing.T) {
+ catalog, err := camel.DefaultCatalog()
+ require.NoError(t, err)
+
+ client, err := test.NewFakeClient()
+ require.NoError(t, err)
+ traitCatalog := trait.NewCatalog(nil)
+
+ environment := trait.Environment{
+ CamelCatalog: catalog,
+ Catalog: traitCatalog,
+ Client: client,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test",
+ Namespace: "ns",
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseInitialization,
+ },
+ Spec: v1.IntegrationSpec{
+ Profile: v1.TraitProfileKnative,
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "Master.java",
+ Content: `from("master:lock:timer:tick").to("log:test")`,
+ },
+ Language: v1.LanguageJavaSource,
+ },
+ },
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ Spec: v1.IntegrationPlatformSpec{
+ Cluster: v1.IntegrationPlatformClusterOpenShift,
+ Build: v1.IntegrationPlatformBuildSpec{
+ PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+ Registry: v1.RegistrySpec{Address: "registry"},
+ RuntimeVersion: catalog.Runtime.Version,
+ },
+ Profile: v1.TraitProfileKnative,
+ },
+ Status: v1.IntegrationPlatformStatus{
+ Phase: v1.IntegrationPlatformPhaseReady,
+ },
+ },
+ EnvVars: make([]corev1.EnvVar, 0),
+ ExecutedTraits: make([]trait.Trait, 0),
+ Resources: kubernetes.NewCollection(),
+ }
+ environment.Platform.ResyncStatusFullConfig()
+
+ mt := NewMasterTrait()
+ mt.InjectClient(client)
+ trait, _ := mt.(*masterTrait)
+ // Initialization phase
+ configured, conditions, err := trait.Configure(&environment)
+ require.NoError(t, err)
+ assert.Empty(t, conditions)
+ assert.True(t, configured)
+ err = trait.Apply(&environment)
+ require.NoError(t, err)
+
+ expectedTrait := &masterTrait{
+ Trait: Trait{
+ Trait: traitv1.Trait{
+ Enabled: ptr.To(true),
+ },
+ ResourceName: ptr.To("test-lock"),
+ LabelValue: ptr.To("test"),
+ },
+ }
+ assert.Equal(t, expectedTrait.Trait, trait.Trait)
+}
diff --git a/addons/resume/resume.go b/addons/resume/resume.go
index 45d56756c7..36cb9fdded 100644
--- a/addons/resume/resume.go
+++ b/addons/resume/resume.go
@@ -20,10 +20,8 @@ package resume
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/metadata"
"github.com/apache/camel-k/v2/pkg/trait"
"github.com/apache/camel-k/v2/pkg/util"
- "github.com/apache/camel-k/v2/pkg/util/log"
"k8s.io/utils/ptr"
)
@@ -46,6 +44,7 @@ import (
type Trait struct {
traitv1.Trait `property:",squash"`
// Enables automatic configuration of the trait.
+ // Deprecated: not in use.
Auto *bool `property:"auto" json:"auto,omitempty"`
// The type of the resume strategy to use
ResumeStrategy string `property:"resume-strategy,omitempty"`
@@ -64,8 +63,8 @@ type resumeTrait struct {
}
const (
- KafkaSingle = "org.apache.camel.processor.resume.kafka.SingleNodeKafkaResumeStrategy"
- StrategyPath = "camel-k-offsets"
+ kafkaSingle = "org.apache.camel.processor.resume.kafka.SingleNodeKafkaResumeStrategy"
+ strategyPath = "camel-k-offsets"
)
func NewResumeTrait() trait.Trait {
@@ -82,28 +81,7 @@ func (r *resumeTrait) Configure(environment *trait.Environment) (bool, *trait.Tr
return false, nil, nil
}
- if ptr.Deref(r.Auto, true) {
- _, err := environment.ConsumeMeta(func(meta metadata.IntegrationMetadata) bool {
- for _, endpoint := range meta.FromURIs {
- log.Infof("Processing component %s", endpoint)
- }
-
- return true
- })
- if err != nil {
- return false, nil, err
- }
-
- if r.ResumeStrategy == "" {
- r.ResumeStrategy = KafkaSingle
- }
-
- if r.ResumePath == "" {
- r.ResumePath = StrategyPath
- }
- }
-
- return r.Enabled != nil && *r.Enabled, nil, nil
+ return ptr.Deref(r.Enabled, false), nil, nil
}
func (r *resumeTrait) Apply(environment *trait.Environment) error {
@@ -113,11 +91,27 @@ func (r *resumeTrait) Apply(environment *trait.Environment) error {
if environment.IntegrationInRunningPhases() {
environment.ApplicationProperties["customizer.resume.enabled"] = "true"
- environment.ApplicationProperties["customizer.resume.resumeStrategy"] = r.ResumeStrategy
- environment.ApplicationProperties["customizer.resume.resumePath"] = r.ResumePath
+ environment.ApplicationProperties["customizer.resume.resumeStrategy"] = r.getResumeStrategy()
+ environment.ApplicationProperties["customizer.resume.resumePath"] = r.getResumePath()
environment.ApplicationProperties["customizer.resume.resumeServer"] = r.ResumeServer
environment.ApplicationProperties["customizer.resume.cacheFillPolicy"] = r.CacheFillPolicy
}
return nil
}
+
+func (r *resumeTrait) getResumeStrategy() string {
+ if r.ResumeStrategy == "" {
+ return kafkaSingle
+ }
+
+ return r.ResumeStrategy
+}
+
+func (r *resumeTrait) getResumePath() string {
+ if r.ResumePath == "" {
+ return strategyPath
+ }
+
+ return r.ResumePath
+}
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index 77c844a218..a9199401aa 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -3533,6 +3533,13 @@ a list of dependencies needed by the application
the profile needed to run this Integration
+|`traits` +
+*xref:#_camel_apache_org_v1_Traits[Traits]*
+|
+
+
+the traits executed for the Integration
+
|`integrationKit` +
*https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core[Kubernetes core/v1.ObjectReference]*
|
@@ -5817,6 +5824,7 @@ TraitConfiguration parameters configuration
* <<#_camel_apache_org_v1_IntegrationPlatformSpec, IntegrationPlatformSpec>>
* <<#_camel_apache_org_v1_IntegrationProfileSpec, IntegrationProfileSpec>>
* <<#_camel_apache_org_v1_IntegrationSpec, IntegrationSpec>>
+* <<#_camel_apache_org_v1_IntegrationStatus, IntegrationStatus>>
Traits represents the collection of trait configurations.
diff --git a/docs/modules/traits/pages/resume.adoc b/docs/modules/traits/pages/resume.adoc
index 894fe4d12c..779b9f1af7 100644
--- a/docs/modules/traits/pages/resume.adoc
+++ b/docs/modules/traits/pages/resume.adoc
@@ -43,6 +43,7 @@ The following configuration options are available:
| resume.auto
| bool
| Enables automatic configuration of the trait.
+Deprecated: not in use.
| resume.resume-strategy,omitempty
| string
diff --git a/helm/camel-k/crds/camel-k-crds.yaml b/helm/camel-k/crds/camel-k-crds.yaml
index 449de8c308..ee85c65f6b 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -19892,6 +19892,1699 @@ spec:
selector:
description: label selector
type: string
+ traits:
+ description: the traits executed for the Integration
+ properties:
+ 3scale:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ addons:
+ additionalProperties:
+ description: AddonTrait represents the configuration of an addon
+ trait.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ description: The extension point with addon traits
+ type: object
+ affinity:
+ description: The configuration of Affinity trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ nodeAffinityLabels:
+ description: Defines a set of nodes the integration pod(s)
+ are eligible to be scheduled on, based on labels on the
+ node.
+ items:
+ type: string
+ type: array
+ podAffinity:
+ description: Always co-locates multiple replicas of the integration
+ in the same node (default `false`).
+ type: boolean
+ podAffinityLabels:
+ description: |-
+ Defines a set of pods (namely those matching the label selector, relative to the given namespace) that the
+ integration pod(s) should be co-located with.
+ items:
+ type: string
+ type: array
+ podAntiAffinity:
+ description: Never co-locates multiple replicas of the integration
+ in the same node (default `false`).
+ type: boolean
+ podAntiAffinityLabels:
+ description: |-
+ Defines a set of pods (namely those matching the label selector, relative to the given namespace) that the
+ integration pod(s) should not be co-located with.
+ items:
+ type: string
+ type: array
+ type: object
+ builder:
+ description: The configuration of Builder trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: When using `pod` strategy, annotation to use
+ for the builder pod.
+ type: object
+ baseImage:
+ description: |-
+ Specify a base image. In order to have the application working properly it must be a container image which has a Java JDK
+ installed and ready to use on path (ie `/usr/bin/java`).
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ incrementalImageBuild:
+ description: Use the incremental image build option, to reuse
+ existing containers (default `true`)
+ type: boolean
+ limitCPU:
+ description: |-
+ When using `pod` strategy, the maximum amount of CPU required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ limitMemory:
+ description: |-
+ When using `pod` strategy, the maximum amount of memory required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ mavenProfiles:
+ description: |-
+ A list of references pointing to configmaps/secrets that contains a maven profile.
+ This configmap/secret is a resource of the IntegrationKit created, therefore it needs to be present in the namespace where the operator is going to create the IntegrationKit.
+ The content of the maven profile is expected to be a text containing a valid maven profile starting with `` and ending with `` that will be integrated as an inline profile in the POM.
+ Syntax: [configmap|secret]:name[/key], where name represents the resource name, key optionally represents the resource key to be filtered (default key value = profile.xml).
+ items:
+ type: string
+ type: array
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: Defines a set of nodes the builder pod is eligible
+ to be scheduled on, based on labels on the node.
+ type: object
+ orderStrategy:
+ description: The build order strategy to use, either `dependencies`,
+ `fifo` or `sequential` (default is the platform default)
+ enum:
+ - dependencies
+ - fifo
+ - sequential
+ type: string
+ platforms:
+ description: The list of manifest platforms to use to build
+ a container image (default `linux/amd64`).
+ items:
+ type: string
+ type: array
+ properties:
+ description: A list of properties to be provided to the build
+ task
+ items:
+ type: string
+ type: array
+ requestCPU:
+ description: |-
+ When using `pod` strategy, the minimum amount of CPU required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ requestMemory:
+ description: |-
+ When using `pod` strategy, the minimum amount of memory required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ strategy:
+ description: The strategy to use, either `pod` or `routine`
+ (default `routine`)
+ enum:
+ - pod
+ - routine
+ type: string
+ tasks:
+ description: A list of tasks to be executed (available only
+ when using `pod` strategy) with format `;;`.
+ items:
+ type: string
+ type: array
+ tasksFilter:
+ description: |-
+ A list of tasks sorted by the order of execution in a csv format, ie, `,,...`.
+ Mind that you must include also the operator tasks (`builder`, `quarkus-native`, `package`, `jib`, `s2i`)
+ if you need to execute them. Useful only with `pod` strategy.
+ type: string
+ tasksLimitCPU:
+ description: A list of limit cpu configuration for the specific
+ task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksLimitMemory:
+ description: A list of limit memory configuration for the
+ specific task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksRequestCPU:
+ description: A list of request cpu configuration for the specific
+ task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksRequestMemory:
+ description: A list of request memory configuration for the
+ specific task with format `:`.
+ items:
+ type: string
+ type: array
+ verbose:
+ description: |-
+ Enable verbose logging on build components that support it (e.g. Kaniko build pod).
+ Deprecated no longer in use
+ type: boolean
+ type: object
+ camel:
+ description: The configuration of Camel trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ properties:
+ description: A list of properties to be provided to the Integration
+ runtime
+ items:
+ type: string
+ type: array
+ runtimeVersion:
+ description: |-
+ The camel-k-runtime version to use for the integration. It overrides the default version set in the Integration Platform.
+ You can use a fixed version (for example "3.2.3") or a semantic version (for example "3.x") which will try to resolve
+ to the best matching Catalog existing on the cluster.
+ type: string
+ type: object
+ container:
+ description: The configuration of Container trait
+ properties:
+ allowPrivilegeEscalation:
+ description: Security Context AllowPrivilegeEscalation configuration
+ (default false).
+ type: boolean
+ auto:
+ description: To automatically enable the trait
+ type: boolean
+ capabilitiesAdd:
+ description: Security Context Capabilities Add configuration
+ (default none).
+ items:
+ description: Capability represent POSIX capabilities type
+ type: string
+ type: array
+ capabilitiesDrop:
+ description: Security Context Capabilities Drop configuration
+ (default ALL).
+ items:
+ description: Capability represent POSIX capabilities type
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ expose:
+ description: Can be used to enable/disable exposure via kubernetes
+ Service.
+ type: boolean
+ image:
+ description: |-
+ The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which
+ won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead
+ Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit.
+ type: string
+ imagePullPolicy:
+ description: 'The pull policy: Always|Never|IfNotPresent'
+ enum:
+ - Always
+ - Never
+ - IfNotPresent
+ type: string
+ limitCPU:
+ description: The maximum amount of CPU to be provided (default
+ 500 millicores).
+ type: string
+ limitMemory:
+ description: The maximum amount of memory to be provided (default
+ 512 Mi).
+ type: string
+ name:
+ description: The main container name. It's named `integration`
+ by default.
+ type: string
+ port:
+ description: To configure a different port exposed by the
+ container (default `8080`).
+ type: integer
+ portName:
+ description: To configure a different port name for the port
+ exposed by the container. It defaults to `http` only when
+ the `expose` parameter is true.
+ type: string
+ requestCPU:
+ description: The minimum amount of CPU required (default 125
+ millicores).
+ type: string
+ requestMemory:
+ description: The minimum amount of memory required (default
+ 128 Mi).
+ type: string
+ runAsNonRoot:
+ description: Security Context RunAsNonRoot configuration (default
+ false).
+ type: boolean
+ runAsUser:
+ description: 'Security Context RunAsUser configuration (default
+ none): this value is automatically retrieved in Openshift
+ clusters when not explicitly set.'
+ format: int64
+ type: integer
+ seccompProfileType:
+ description: Security Context SeccompProfileType configuration
+ (default RuntimeDefault).
+ enum:
+ - Unconfined
+ - RuntimeDefault
+ type: string
+ servicePort:
+ description: To configure under which service port the container
+ port is to be exposed (default `80`).
+ type: integer
+ servicePortName:
+ description: To configure under which service port name the
+ container port is to be exposed (default `http`).
+ type: string
+ type: object
+ cron:
+ description: The configuration of Cron trait
+ properties:
+ activeDeadlineSeconds:
+ description: |-
+ Specifies the duration in seconds, relative to the start time, that the job
+ may be continuously active before it is considered to be failed.
+ It defaults to 60s.
+ format: int64
+ type: integer
+ auto:
+ description: |-
+ Automatically deploy the integration as CronJob when all routes are
+ either starting from a periodic consumer (only `cron`, `timer` and `quartz` are supported) or a passive consumer (e.g. `direct` is a passive consumer).
+
+
+ It's required that all periodic consumers have the same period, and it can be expressed as cron schedule (e.g. `1m` can be expressed as `0/1 * * * *`,
+ while `35m` or `50s` cannot).
+ type: boolean
+ backoffLimit:
+ description: |-
+ Specifies the number of retries before marking the job failed.
+ It defaults to 2.
+ format: int32
+ type: integer
+ components:
+ description: |-
+ A comma separated list of the Camel components that need to be customized in order for them to work when the schedule is triggered externally by Kubernetes.
+ A specific customizer is activated for each specified component. E.g. for the `timer` component, the `cron-timer` customizer is
+ activated (it's present in the `org.apache.camel.k:camel-k-cron` library).
+
+
+ Supported components are currently: `cron`, `timer` and `quartz`.
+ type: string
+ concurrencyPolicy:
+ description: |-
+ Specifies how to treat concurrent executions of a Job.
+ Valid values are:
+ - "Allow": allows CronJobs to run concurrently;
+ - "Forbid" (default): forbids concurrent runs, skipping next run if previous run hasn't finished yet;
+ - "Replace": cancels currently running job and replaces it with a new one
+ enum:
+ - Allow
+ - Forbid
+ - Replace
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ fallback:
+ description: |-
+ Use the default Camel implementation of the `cron` endpoint (`quartz`) instead of trying to materialize the integration
+ as Kubernetes CronJob.
+ type: boolean
+ schedule:
+ description: |-
+ The CronJob schedule for the whole integration. If multiple routes are declared, they must have the same schedule for this
+ mechanism to work correctly.
+ type: string
+ startingDeadlineSeconds:
+ description: |-
+ Optional deadline in seconds for starting the job if it misses scheduled
+ time for any reason. Missed jobs executions will be counted as failed ones.
+ format: int64
+ type: integer
+ timeZone:
+ description: The timezone that the CronJob will run on
+ type: string
+ type: object
+ dependencies:
+ description: The configuration of Dependencies trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ type: object
+ deployer:
+ description: The configuration of Deployer trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ kind:
+ description: Allows to explicitly select the desired deployment
+ kind between `deployment`, `cron-job` or `knative-service`
+ when creating the resources for running the integration.
+ enum:
+ - deployment
+ - cron-job
+ - knative-service
+ type: string
+ useSSA:
+ description: |-
+ Deprecated: won't be able to enforce client side update in the future.
+ Use server-side apply to update the owned resources (default `true`).
+ Note that it automatically falls back to client-side patching, if SSA is not available, e.g., on old Kubernetes clusters.
+ type: boolean
+ type: object
+ deployment:
+ description: The configuration of Deployment trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ progressDeadlineSeconds:
+ description: |-
+ The maximum time in seconds for the deployment to make progress before it
+ is considered to be failed. It defaults to `60s`.
+ format: int32
+ type: integer
+ rollingUpdateMaxSurge:
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ The maximum number of pods that can be scheduled above the desired number of
+ pods.
+ Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ This can not be 0 if MaxUnavailable is 0.
+ Absolute number is calculated from percentage by rounding up.
+ Defaults to `25%`.
+ x-kubernetes-int-or-string: true
+ rollingUpdateMaxUnavailable:
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ The maximum number of pods that can be unavailable during the update.
+ Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ Absolute number is calculated from percentage by rounding down.
+ This can not be 0 if MaxSurge is 0.
+ Defaults to `25%`.
+ x-kubernetes-int-or-string: true
+ strategy:
+ description: The deployment strategy to use to replace existing
+ pods with new ones.
+ enum:
+ - Recreate
+ - RollingUpdate
+ type: string
+ type: object
+ environment:
+ description: The configuration of Environment trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ containerMeta:
+ description: Enables injection of `NAMESPACE` and `POD_NAME`
+ environment variables (default `true`)
+ type: boolean
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ httpProxy:
+ description: Propagates the `HTTP_PROXY`, `HTTPS_PROXY` and
+ `NO_PROXY` environment variables (default `true`)
+ type: boolean
+ vars:
+ description: |-
+ A list of environment variables to be added to the integration container.
+ The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
+ and key represents the resource key to be mapped as and environment variable.
+ These take precedence over any previously defined environment variables.
+ items:
+ type: string
+ type: array
+ type: object
+ error-handler:
+ description: The configuration of Error Handler trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ ref:
+ description: The error handler ref name provided or found
+ in application properties
+ type: string
+ type: object
+ gc:
+ description: The configuration of GC trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ discoveryCache:
+ description: |-
+ Discovery client cache to be used, either `disabled`, `disk` or `memory` (default `memory`).
+ Deprecated: to be removed from trait configuration.
+ enum:
+ - disabled
+ - disk
+ - memory
+ type: string
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ health:
+ description: The configuration of Health trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ livenessFailureThreshold:
+ description: Minimum consecutive failures for the liveness
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ livenessInitialDelay:
+ description: Number of seconds after the container has started
+ before the liveness probe is initiated.
+ format: int32
+ type: integer
+ livenessPeriod:
+ description: How often to perform the liveness probe.
+ format: int32
+ type: integer
+ livenessProbe:
+ description: The liveness probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ livenessProbeEnabled:
+ description: Configures the liveness probe for the integration
+ container (default `false`).
+ type: boolean
+ livenessScheme:
+ description: Scheme to use when connecting to the liveness
+ probe (default `HTTP`).
+ type: string
+ livenessSuccessThreshold:
+ description: Minimum consecutive successes for the liveness
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ livenessTimeout:
+ description: Number of seconds after which the liveness probe
+ times out.
+ format: int32
+ type: integer
+ readinessFailureThreshold:
+ description: Minimum consecutive failures for the readiness
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ readinessInitialDelay:
+ description: Number of seconds after the container has started
+ before the readiness probe is initiated.
+ format: int32
+ type: integer
+ readinessPeriod:
+ description: How often to perform the readiness probe.
+ format: int32
+ type: integer
+ readinessProbe:
+ description: The readiness probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ readinessProbeEnabled:
+ description: Configures the readiness probe for the integration
+ container (default `true`).
+ type: boolean
+ readinessScheme:
+ description: Scheme to use when connecting to the readiness
+ probe (default `HTTP`).
+ type: string
+ readinessSuccessThreshold:
+ description: Minimum consecutive successes for the readiness
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ readinessTimeout:
+ description: Number of seconds after which the readiness probe
+ times out.
+ format: int32
+ type: integer
+ startupFailureThreshold:
+ description: Minimum consecutive failures for the startup
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ startupInitialDelay:
+ description: Number of seconds after the container has started
+ before the startup probe is initiated.
+ format: int32
+ type: integer
+ startupPeriod:
+ description: How often to perform the startup probe.
+ format: int32
+ type: integer
+ startupProbe:
+ description: The startup probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ startupProbeEnabled:
+ description: Configures the startup probe for the integration
+ container (default `false`).
+ type: boolean
+ startupScheme:
+ description: Scheme to use when connecting to the startup
+ probe (default `HTTP`).
+ type: string
+ startupSuccessThreshold:
+ description: Minimum consecutive successes for the startup
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ startupTimeout:
+ description: Number of seconds after which the startup probe
+ times out.
+ format: int32
+ type: integer
+ type: object
+ ingress:
+ description: The configuration of Ingress trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to the ingress.
+ This can be used to set controller specific annotations, e.g., when using the NGINX Ingress controller:
+ See https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md
+ type: object
+ auto:
+ description: To automatically add an ingress whenever the
+ integration uses an HTTP endpoint consumer.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ host:
+ description: To configure the host exposed by the ingress.
+ type: string
+ ingressClassName:
+ description: |-
+ The Ingress class name as defined by the Ingress spec
+ See https://kubernetes.io/docs/concepts/services-networking/ingress/
+ type: string
+ path:
+ description: To configure the path exposed by the ingress
+ (default `/`).
+ type: string
+ pathType:
+ description: |-
+ To configure the path type exposed by the ingress.
+ One of `Exact`, `Prefix`, `ImplementationSpecific` (default to `Prefix`).
+ enum:
+ - Exact
+ - Prefix
+ - ImplementationSpecific
+ type: string
+ tlsHosts:
+ description: To configure tls hosts
+ items:
+ type: string
+ type: array
+ tlsSecretName:
+ description: To configure tls secret name
+ type: string
+ type: object
+ istio:
+ description: The configuration of Istio trait
+ properties:
+ allow:
+ description: Configures a (comma-separated) list of CIDR subnets
+ that should not be intercepted by the Istio proxy (`10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`
+ by default).
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ inject:
+ description: Forces the value for labels `sidecar.istio.io/inject`.
+ By default the label is set to `true` on deployment and
+ not set on Knative Service.
+ type: boolean
+ type: object
+ jolokia:
+ description: The configuration of Jolokia trait
+ properties:
+ CACert:
+ description: |-
+ The PEM encoded CA certification file path, used to verify client certificates,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` for OpenShift).
+ type: string
+ clientPrincipal:
+ description: |-
+ The principal(s) which must be given in a client certificate to allow access to the Jolokia endpoint,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `clientPrincipal=cn=system:master-proxy`, `cn=hawtio-online.hawtio.svc` and `cn=fuse-console.fuse.svc` for OpenShift).
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ discoveryEnabled:
+ description: Listen for multicast requests (default `false`)
+ type: boolean
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ extendedClientCheck:
+ description: |-
+ Mandate the client certificate contains a client flag in the extended key usage section,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `true` for OpenShift).
+ type: boolean
+ host:
+ description: |-
+ The Host address to which the Jolokia agent should bind to. If `"\*"` or `"0.0.0.0"` is given,
+ the servers binds to every network interface (default `"*"`).
+ type: string
+ options:
+ description: |-
+ A list of additional Jolokia options as defined
+ in https://jolokia.org/reference/html/agents.html#agent-jvm-config[JVM agent configuration options]
+ items:
+ type: string
+ type: array
+ password:
+ description: The password used for authentication, applicable
+ when the `user` option is set.
+ type: string
+ port:
+ description: The Jolokia endpoint port (default `8778`).
+ type: integer
+ protocol:
+ description: The protocol to use, either `http` or `https`
+ (default `https` for OpenShift)
+ type: string
+ useSSLClientAuthentication:
+ description: Whether client certificates should be used for
+ authentication (default `true` for OpenShift).
+ type: boolean
+ user:
+ description: The user to be used for authentication
+ type: string
+ type: object
+ jvm:
+ description: The configuration of JVM trait
+ properties:
+ classpath:
+ description: Additional JVM classpath (use `Linux` classpath
+ separator)
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ debug:
+ description: Activates remote debugging, so that a debugger
+ can be attached to the JVM, e.g., using port-forwarding
+ type: boolean
+ debugAddress:
+ description: Transport address at which to listen for the
+ newly launched JVM (default `*:5005`)
+ type: string
+ debugSuspend:
+ description: Suspends the target JVM immediately before the
+ main class is loaded
+ type: boolean
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ jar:
+ description: The Jar dependency which will run the application.
+ Leave it empty for managed Integrations.
+ type: string
+ options:
+ description: A list of JVM options
+ items:
+ type: string
+ type: array
+ printCommand:
+ description: |-
+ Prints the command used the start the JVM in the container logs (default `true`)
+ Deprecated: no longer in use.
+ type: boolean
+ type: object
+ kamelets:
+ description: The configuration of Kamelets trait
+ properties:
+ auto:
+ description: Automatically inject all referenced Kamelets
+ and their default configuration (enabled by default)
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ list:
+ description: Comma separated list of Kamelet names to load
+ into the current integration
+ type: string
+ mountPoint:
+ description: The directory where the application mounts and
+ reads Kamelet spec (default `/etc/camel/kamelets`)
+ type: string
+ type: object
+ keda:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ knative:
+ description: The configuration of Knative trait
+ properties:
+ auto:
+ description: Enable automatic discovery of all trait properties.
+ type: boolean
+ channelSinks:
+ description: |-
+ List of channels used as destination of integration routes.
+ Can contain simple channel names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ channelSources:
+ description: |-
+ List of channels used as source of integration routes.
+ Can contain simple channel names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ config:
+ description: Can be used to inject a Knative complete configuration
+ in JSON format.
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ endpointSinks:
+ description: |-
+ List of endpoints used as destination of integration routes.
+ Can contain simple endpoint names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ endpointSources:
+ description: List of channels used as source of integration
+ routes.
+ items:
+ type: string
+ type: array
+ eventSinks:
+ description: |-
+ List of event types that the integration will produce.
+ Can contain simple event types or full Camel URIs (to use a specific broker).
+ items:
+ type: string
+ type: array
+ eventSources:
+ description: |-
+ List of event types that the integration will be subscribed to.
+ Can contain simple event types or full Camel URIs (to use a specific broker different from "default").
+ items:
+ type: string
+ type: array
+ filterEventType:
+ description: |-
+ Enables the default filtering for the Knative trigger using the event type
+ If this is true, the created Knative trigger uses the event type as a filter on the event stream when no other filter criteria is given. (default: true)
+ type: boolean
+ filterSourceChannels:
+ description: |-
+ Enables filtering on events based on the header "ce-knativehistory". Since this header has been removed in newer versions of
+ Knative, filtering is disabled by default.
+ type: boolean
+ filters:
+ description: |-
+ Sets filter attributes on the event stream (such as event type, source, subject and so on).
+ A list of key-value pairs that represent filter attributes and its values.
+ The syntax is KEY=VALUE, e.g., `source="my.source"`.
+ Filter attributes get set on the Knative trigger that is being created as part of this integration.
+ items:
+ type: string
+ type: array
+ namespaceLabel:
+ description: |-
+ Enables the camel-k-operator to set the "bindings.knative.dev/include=true" label to the namespace
+ As Knative requires this label to perform injection of K_SINK URL into the service.
+ If this is false, the integration pod may start and fail, read the SinkBinding Knative documentation. (default: true)
+ type: boolean
+ sinkBinding:
+ description: |-
+ Allows binding the integration to a sink via a Knative SinkBinding resource.
+ This can be used when the integration targets a single sink.
+ It's enabled by default when the integration targets a single sink
+ (except when the integration is owned by a Knative source).
+ type: boolean
+ type: object
+ knative-service:
+ description: The configuration of Knative Service trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to route.
+ This can be used to set knative service specific annotations
+ CLI usage example: -t "knative-service.annotations.'haproxy.router.openshift.io/balance'=true"
+ type: object
+ auto:
+ description: |-
+ Automatically deploy the integration as Knative service when all conditions hold:
+
+
+ * Integration is using the Knative profile
+ * All routes are either starting from an HTTP based consumer or a passive consumer (e.g. `direct` is a passive consumer)
+ type: boolean
+ autoscalingMetric:
+ description: |-
+ Configures the Knative autoscaling metric property (e.g. to set `concurrency` based or `cpu` based autoscaling).
+
+
+ Refer to the Knative documentation for more information.
+ type: string
+ autoscalingTarget:
+ description: |-
+ Sets the allowed concurrency level or CPU percentage (depending on the autoscaling metric) for each Pod.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ class:
+ description: |-
+ Configures the Knative autoscaling class property (e.g. to set `hpa.autoscaling.knative.dev` or `kpa.autoscaling.knative.dev` autoscaling).
+
+
+ Refer to the Knative documentation for more information.
+ enum:
+ - kpa.autoscaling.knative.dev
+ - hpa.autoscaling.knative.dev
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ maxScale:
+ description: |-
+ An upper bound for the number of Pods that can be running in parallel for the integration.
+ Knative has its own cap value that depends on the installation.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ minScale:
+ description: |-
+ The minimum number of Pods that should be running at any time for the integration. It's **zero** by default, meaning that
+ the integration is scaled down to zero when not used for a configured amount of time.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ rolloutDuration:
+ description: |-
+ Enables to gradually shift traffic to the latest Revision and sets the rollout duration.
+ It's disabled by default and must be expressed as a Golang `time.Duration` string representation,
+ rounded to a second precision.
+ type: string
+ timeoutSeconds:
+ description: |-
+ The maximum duration in seconds that the request instance is allowed to respond to a request.
+ This field propagates to the integration pod's terminationGracePeriodSeconds
+
+
+ Refer to the Knative documentation for more information.
+ format: int64
+ type: integer
+ visibility:
+ description: |-
+ Setting `cluster-local`, Knative service becomes a private service.
+ Specifically, this option applies the `networking.knative.dev/visibility` label to Knative service.
+
+
+ Refer to the Knative documentation for more information.
+ enum:
+ - cluster-local
+ type: string
+ type: object
+ logging:
+ description: The configuration of Logging trait
+ properties:
+ color:
+ description: Colorize the log output
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ format:
+ description: Logs message format
+ type: string
+ json:
+ description: Output the logs in JSON
+ type: boolean
+ jsonPrettyPrint:
+ description: Enable "pretty printing" of the JSON logs
+ type: boolean
+ level:
+ description: Adjust the logging level (defaults to `INFO`)
+ enum:
+ - FATAL
+ - WARN
+ - INFO
+ - DEBUG
+ - TRACE
+ type: string
+ type: object
+ master:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ mount:
+ description: The configuration of Mount trait
+ properties:
+ configs:
+ description: |-
+ A list of configuration pointing to configmap/secret.
+ The configuration are expected to be UTF-8 resources as they are processed by runtime Camel Context and tried to be parsed as property files.
+ They are also made available on the classpath in order to ease their usage directly from the Route.
+ Syntax: [configmap|secret]:name[/key], where name represents the resource name and key optionally represents the resource key to be filtered
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ emptyDirs:
+ description: 'A list of EmptyDir volumes to be mounted. Syntax:
+ [name:/container/path]'
+ items:
+ type: string
+ type: array
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ hotReload:
+ description: |-
+ Enable "hot reload" when a secret/configmap mounted is edited (default `false`). The configmap/secret must be
+ marked with `camel.apache.org/integration` label to be taken in account. The resource will be watched for any kind change, also for
+ changes in metadata.
+ type: boolean
+ resources:
+ description: |-
+ A list of resources (text or binary content) pointing to configmap/secret.
+ The resources are expected to be any resource type (text or binary content).
+ The destination path can be either a default location or any path specified by the user.
+ Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
+ items:
+ type: string
+ type: array
+ scanKameletsImplicitLabelSecrets:
+ description: 'Deprecated: no longer available since version
+ 2.5.'
+ type: boolean
+ volumes:
+ description: 'A list of Persistent Volume Claims to be mounted.
+ Syntax: [pvcname:/container/path]'
+ items:
+ type: string
+ type: array
+ type: object
+ openapi:
+ description: The configuration of OpenAPI trait
+ properties:
+ configmaps:
+ description: The configmaps holding the spec of the OpenAPI
+ (compatible with > 3.0 spec only).
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ type: object
+ owner:
+ description: The configuration of Owner trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ targetAnnotations:
+ description: The set of annotations to be transferred
+ items:
+ type: string
+ type: array
+ targetLabels:
+ description: The set of labels to be transferred
+ items:
+ type: string
+ type: array
+ type: object
+ pdb:
+ description: The configuration of PDB trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ maxUnavailable:
+ description: |-
+ The number of pods for the Integration that can be unavailable after an eviction.
+ It can be either an absolute number or a percentage (default `1` if `min-available` is also not set).
+ Only one of `max-unavailable` and `min-available` can be specified.
+ type: string
+ minAvailable:
+ description: |-
+ The number of pods for the Integration that must still be available after an eviction.
+ It can be either an absolute number or a percentage.
+ Only one of `min-available` and `max-unavailable` can be specified.
+ type: string
+ type: object
+ platform:
+ description: The configuration of Platform trait
+ properties:
+ auto:
+ description: |-
+ To automatically detect from the environment if a default platform can be created (it will be created on OpenShift or when a registry address is set).
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ createDefault:
+ description: |-
+ To create a default (empty) platform when the platform is missing.
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ global:
+ description: |-
+ Indicates if the platform should be created globally in the case of global operator (default true).
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ type: object
+ pod:
+ description: The configuration of Pod trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ prometheus:
+ description: The configuration of Prometheus trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ podMonitor:
+ description: Whether a `PodMonitor` resource is created (default
+ `true`).
+ type: boolean
+ podMonitorLabels:
+ description: The `PodMonitor` resource labels, applicable
+ when `pod-monitor` is `true`.
+ items:
+ type: string
+ type: array
+ type: object
+ pull-secret:
+ description: The configuration of Pull Secret trait
+ properties:
+ auto:
+ description: Automatically configures the platform registry
+ secret on the pod if it is of type `kubernetes.io/dockerconfigjson`.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ imagePullerDelegation:
+ description: When using a global operator with a shared platform,
+ this enables delegation of the `system:image-puller` cluster
+ role on the operator namespace to the integration service
+ account.
+ type: boolean
+ secretName:
+ description: The pull secret name to set on the Pod. If left
+ empty this is automatically taken from the `IntegrationPlatform`
+ registry configuration.
+ type: string
+ type: object
+ quarkus:
+ description: The configuration of Quarkus trait
+ properties:
+ buildMode:
+ description: |-
+ The Quarkus mode to run: either `jvm` or `native` (default `jvm`).
+ In case both `jvm` and `native` are specified, two `IntegrationKit` resources are created,
+ with the `native` kit having precedence over the `jvm` one once ready.
+ items:
+ description: QuarkusMode is the type of Quarkus build packaging.
+ enum:
+ - jvm
+ - native
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ nativeBaseImage:
+ description: The base image to use when running a native build
+ (default `quay.io/quarkus/quarkus-micro-image:2.0`)
+ type: string
+ nativeBuilderImage:
+ description: The image containing the tooling required for
+ a native build (by default it will use the one provided
+ in the runtime catalog)
+ type: string
+ packageTypes:
+ description: |-
+ The Quarkus package types, `fast-jar` or `native` (default `fast-jar`).
+ In case both `fast-jar` and `native` are specified, two `IntegrationKit` resources are created,
+ with the native kit having precedence over the `fast-jar` one once ready.
+ The order influences the resolution of the current kit for the integration.
+ The kit corresponding to the first package type will be assigned to the
+ integration in case no existing kit that matches the integration exists.
+ Deprecated: use `build-mode` instead.
+ items:
+ description: |-
+ QuarkusPackageType is the type of Quarkus build packaging.
+ Deprecated: use `QuarkusMode` instead.
+ enum:
+ - fast-jar
+ - native
+ type: string
+ type: array
+ type: object
+ registry:
+ description: |-
+ The configuration of Registry trait (support removed since version 2.5.0).
+ Deprecated: use jvm trait or read documentation.
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ route:
+ description: The configuration of Route trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to route.
+ This can be used to set route specific annotations
+ For annotations options see https://docs.openshift.com/container-platform/3.11/architecture/networking/routes.html#route-specific-annotations
+ CLI usage example: -t "route.annotations.'haproxy.router.openshift.io/balance'=true"
+ type: object
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ host:
+ description: To configure the host exposed by the route.
+ type: string
+ tlsCACertificate:
+ description: |-
+ The TLS CA certificate contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCACertificateSecret:
+ description: |-
+ The secret name and key reference to the TLS CA certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCertificate:
+ description: |-
+ The TLS certificate contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCertificateSecret:
+ description: |-
+ The secret name and key reference to the TLS certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsDestinationCACertificate:
+ description: |-
+ The destination CA certificate provides the contents of the ca certificate of the final destination. When using reencrypt
+ termination this file should be provided in order to have routers use it for health checks on the secure connection.
+ If this field is not specified, the router may provide its own destination CA and perform hostname validation using
+ the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically
+ verify.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsDestinationCACertificateSecret:
+ description: |-
+ The secret name and key reference to the destination CA certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsInsecureEdgeTerminationPolicy:
+ description: |-
+ To configure how to deal with insecure traffic, e.g. `Allow`, `Disable` or `Redirect` traffic.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ enum:
+ - None
+ - Allow
+ - Redirect
+ type: string
+ tlsKey:
+ description: |-
+ The TLS certificate key contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsKeySecret:
+ description: |-
+ The secret name and key reference to the TLS certificate key. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsTermination:
+ description: |-
+ The TLS termination type, like `edge`, `passthrough` or `reencrypt`.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ enum:
+ - edge
+ - reencrypt
+ - passthrough
+ type: string
+ type: object
+ security-context:
+ description: The configuration of Security Context trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ runAsNonRoot:
+ description: Security Context RunAsNonRoot configuration (default
+ false).
+ type: boolean
+ runAsUser:
+ description: 'Security Context RunAsUser configuration (default
+ none): this value is automatically retrieved in Openshift
+ clusters when not explicitly set.'
+ format: int64
+ type: integer
+ seccompProfileType:
+ description: Security Context SeccompProfileType configuration
+ (default RuntimeDefault).
+ enum:
+ - Unconfined
+ - RuntimeDefault
+ type: string
+ type: object
+ service:
+ description: The configuration of Service trait
+ properties:
+ auto:
+ description: To automatically detect from the code if a Service
+ needs to be created.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ nodePort:
+ description: |-
+ Enable Service to be exposed as NodePort (default `false`).
+ Deprecated: Use service type instead.
+ type: boolean
+ type:
+ description: The type of service to be used, either 'ClusterIP',
+ 'NodePort' or 'LoadBalancer'.
+ enum:
+ - ClusterIP
+ - NodePort
+ - LoadBalancer
+ type: string
+ type: object
+ service-binding:
+ description: The configuration of Service Binding trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ services:
+ description: List of Services in the form [[apigroup/]version:]kind:[namespace/]name
+ items:
+ type: string
+ type: array
+ type: object
+ strimzi:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ telemetry:
+ description: The configuration of Telemetry trait
+ properties:
+ auto:
+ description: Enables automatic configuration of the trait,
+ including automatic discovery of the telemetry endpoint.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ endpoint:
+ description: The target endpoint of the Telemetry service
+ (automatically discovered by default)
+ type: string
+ sampler:
+ description: The sampler of the telemetry used for tracing
+ (default "on")
+ type: string
+ sampler-parent-based:
+ description: The sampler of the telemetry used for tracing
+ is parent based (default "true")
+ type: boolean
+ sampler-ratio:
+ description: The sampler ratio of the telemetry used for tracing
+ type: string
+ serviceName:
+ description: The name of the service that publishes telemetry
+ data (defaults to the integration name)
+ type: string
+ type: object
+ toleration:
+ description: The configuration of Toleration trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ taints:
+ description: The list of taints to tolerate, in the form `Key[=Value]:Effect[:Seconds]`
+ items:
+ type: string
+ type: array
+ type: object
+ tracing:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ type: object
version:
description: the operator version
type: string
diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go
index 96e429bd1a..d31db2cb27 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -97,6 +97,8 @@ type IntegrationStatus struct {
Dependencies []string `json:"dependencies,omitempty"`
// the profile needed to run this Integration
Profile TraitProfile `json:"profile,omitempty"`
+ // the traits executed for the Integration
+ Traits *Traits `json:"traits,omitempty"`
// the reference of the `IntegrationKit` which is used for this Integration
IntegrationKit *corev1.ObjectReference `json:"integrationKit,omitempty"`
// The IntegrationPlatform watching this Integration
diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go
index 64fa10e2bd..a4362f7409 100644
--- a/pkg/apis/camel/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go
@@ -1838,6 +1838,11 @@ func (in *IntegrationStatus) DeepCopyInto(out *IntegrationStatus) {
*out = make([]string, len(*in))
copy(*out, *in)
}
+ if in.Traits != nil {
+ in, out := &in.Traits, &out.Traits
+ *out = new(Traits)
+ (*in).DeepCopyInto(*out)
+ }
if in.IntegrationKit != nil {
in, out := &in.IntegrationKit, &out.IntegrationKit
*out = new(corev1.ObjectReference)
diff --git a/pkg/client/camel/applyconfiguration/camel/v1/integrationstatus.go b/pkg/client/camel/applyconfiguration/camel/v1/integrationstatus.go
index 851decd192..12a1980cb8 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/integrationstatus.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/integrationstatus.go
@@ -34,6 +34,7 @@ type IntegrationStatusApplyConfiguration struct {
Image *string `json:"image,omitempty"`
Dependencies []string `json:"dependencies,omitempty"`
Profile *v1.TraitProfile `json:"profile,omitempty"`
+ Traits *TraitsApplyConfiguration `json:"traits,omitempty"`
IntegrationKit *corev1.ObjectReference `json:"integrationKit,omitempty"`
Platform *string `json:"platform,omitempty"`
GeneratedSources []SourceSpecApplyConfiguration `json:"generatedSources,omitempty"`
@@ -105,6 +106,14 @@ func (b *IntegrationStatusApplyConfiguration) WithProfile(value v1.TraitProfile)
return b
}
+// WithTraits sets the Traits field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Traits field is set to the value of the last call.
+func (b *IntegrationStatusApplyConfiguration) WithTraits(value *TraitsApplyConfiguration) *IntegrationStatusApplyConfiguration {
+ b.Traits = value
+ return b
+}
+
// WithIntegrationKit sets the IntegrationKit field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the IntegrationKit field is set to the value of the last call.
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 20be245607..a89e55bd13 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -8357,6 +8357,1699 @@ spec:
selector:
description: label selector
type: string
+ traits:
+ description: the traits executed for the Integration
+ properties:
+ 3scale:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ addons:
+ additionalProperties:
+ description: AddonTrait represents the configuration of an addon
+ trait.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ description: The extension point with addon traits
+ type: object
+ affinity:
+ description: The configuration of Affinity trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ nodeAffinityLabels:
+ description: Defines a set of nodes the integration pod(s)
+ are eligible to be scheduled on, based on labels on the
+ node.
+ items:
+ type: string
+ type: array
+ podAffinity:
+ description: Always co-locates multiple replicas of the integration
+ in the same node (default `false`).
+ type: boolean
+ podAffinityLabels:
+ description: |-
+ Defines a set of pods (namely those matching the label selector, relative to the given namespace) that the
+ integration pod(s) should be co-located with.
+ items:
+ type: string
+ type: array
+ podAntiAffinity:
+ description: Never co-locates multiple replicas of the integration
+ in the same node (default `false`).
+ type: boolean
+ podAntiAffinityLabels:
+ description: |-
+ Defines a set of pods (namely those matching the label selector, relative to the given namespace) that the
+ integration pod(s) should not be co-located with.
+ items:
+ type: string
+ type: array
+ type: object
+ builder:
+ description: The configuration of Builder trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: When using `pod` strategy, annotation to use
+ for the builder pod.
+ type: object
+ baseImage:
+ description: |-
+ Specify a base image. In order to have the application working properly it must be a container image which has a Java JDK
+ installed and ready to use on path (ie `/usr/bin/java`).
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ incrementalImageBuild:
+ description: Use the incremental image build option, to reuse
+ existing containers (default `true`)
+ type: boolean
+ limitCPU:
+ description: |-
+ When using `pod` strategy, the maximum amount of CPU required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ limitMemory:
+ description: |-
+ When using `pod` strategy, the maximum amount of memory required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ mavenProfiles:
+ description: |-
+ A list of references pointing to configmaps/secrets that contains a maven profile.
+ This configmap/secret is a resource of the IntegrationKit created, therefore it needs to be present in the namespace where the operator is going to create the IntegrationKit.
+ The content of the maven profile is expected to be a text containing a valid maven profile starting with `` and ending with `` that will be integrated as an inline profile in the POM.
+ Syntax: [configmap|secret]:name[/key], where name represents the resource name, key optionally represents the resource key to be filtered (default key value = profile.xml).
+ items:
+ type: string
+ type: array
+ nodeSelector:
+ additionalProperties:
+ type: string
+ description: Defines a set of nodes the builder pod is eligible
+ to be scheduled on, based on labels on the node.
+ type: object
+ orderStrategy:
+ description: The build order strategy to use, either `dependencies`,
+ `fifo` or `sequential` (default is the platform default)
+ enum:
+ - dependencies
+ - fifo
+ - sequential
+ type: string
+ platforms:
+ description: The list of manifest platforms to use to build
+ a container image (default `linux/amd64`).
+ items:
+ type: string
+ type: array
+ properties:
+ description: A list of properties to be provided to the build
+ task
+ items:
+ type: string
+ type: array
+ requestCPU:
+ description: |-
+ When using `pod` strategy, the minimum amount of CPU required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ requestMemory:
+ description: |-
+ When using `pod` strategy, the minimum amount of memory required by the pod builder.
+ Deprecated: use TasksRequestCPU instead with task name `builder`.
+ type: string
+ strategy:
+ description: The strategy to use, either `pod` or `routine`
+ (default `routine`)
+ enum:
+ - pod
+ - routine
+ type: string
+ tasks:
+ description: A list of tasks to be executed (available only
+ when using `pod` strategy) with format `;;`.
+ items:
+ type: string
+ type: array
+ tasksFilter:
+ description: |-
+ A list of tasks sorted by the order of execution in a csv format, ie, `,,...`.
+ Mind that you must include also the operator tasks (`builder`, `quarkus-native`, `package`, `jib`, `s2i`)
+ if you need to execute them. Useful only with `pod` strategy.
+ type: string
+ tasksLimitCPU:
+ description: A list of limit cpu configuration for the specific
+ task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksLimitMemory:
+ description: A list of limit memory configuration for the
+ specific task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksRequestCPU:
+ description: A list of request cpu configuration for the specific
+ task with format `:`.
+ items:
+ type: string
+ type: array
+ tasksRequestMemory:
+ description: A list of request memory configuration for the
+ specific task with format `:`.
+ items:
+ type: string
+ type: array
+ verbose:
+ description: |-
+ Enable verbose logging on build components that support it (e.g. Kaniko build pod).
+ Deprecated no longer in use
+ type: boolean
+ type: object
+ camel:
+ description: The configuration of Camel trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ properties:
+ description: A list of properties to be provided to the Integration
+ runtime
+ items:
+ type: string
+ type: array
+ runtimeVersion:
+ description: |-
+ The camel-k-runtime version to use for the integration. It overrides the default version set in the Integration Platform.
+ You can use a fixed version (for example "3.2.3") or a semantic version (for example "3.x") which will try to resolve
+ to the best matching Catalog existing on the cluster.
+ type: string
+ type: object
+ container:
+ description: The configuration of Container trait
+ properties:
+ allowPrivilegeEscalation:
+ description: Security Context AllowPrivilegeEscalation configuration
+ (default false).
+ type: boolean
+ auto:
+ description: To automatically enable the trait
+ type: boolean
+ capabilitiesAdd:
+ description: Security Context Capabilities Add configuration
+ (default none).
+ items:
+ description: Capability represent POSIX capabilities type
+ type: string
+ type: array
+ capabilitiesDrop:
+ description: Security Context Capabilities Drop configuration
+ (default ALL).
+ items:
+ description: Capability represent POSIX capabilities type
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ expose:
+ description: Can be used to enable/disable exposure via kubernetes
+ Service.
+ type: boolean
+ image:
+ description: |-
+ The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which
+ won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead
+ Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit.
+ type: string
+ imagePullPolicy:
+ description: 'The pull policy: Always|Never|IfNotPresent'
+ enum:
+ - Always
+ - Never
+ - IfNotPresent
+ type: string
+ limitCPU:
+ description: The maximum amount of CPU to be provided (default
+ 500 millicores).
+ type: string
+ limitMemory:
+ description: The maximum amount of memory to be provided (default
+ 512 Mi).
+ type: string
+ name:
+ description: The main container name. It's named `integration`
+ by default.
+ type: string
+ port:
+ description: To configure a different port exposed by the
+ container (default `8080`).
+ type: integer
+ portName:
+ description: To configure a different port name for the port
+ exposed by the container. It defaults to `http` only when
+ the `expose` parameter is true.
+ type: string
+ requestCPU:
+ description: The minimum amount of CPU required (default 125
+ millicores).
+ type: string
+ requestMemory:
+ description: The minimum amount of memory required (default
+ 128 Mi).
+ type: string
+ runAsNonRoot:
+ description: Security Context RunAsNonRoot configuration (default
+ false).
+ type: boolean
+ runAsUser:
+ description: 'Security Context RunAsUser configuration (default
+ none): this value is automatically retrieved in Openshift
+ clusters when not explicitly set.'
+ format: int64
+ type: integer
+ seccompProfileType:
+ description: Security Context SeccompProfileType configuration
+ (default RuntimeDefault).
+ enum:
+ - Unconfined
+ - RuntimeDefault
+ type: string
+ servicePort:
+ description: To configure under which service port the container
+ port is to be exposed (default `80`).
+ type: integer
+ servicePortName:
+ description: To configure under which service port name the
+ container port is to be exposed (default `http`).
+ type: string
+ type: object
+ cron:
+ description: The configuration of Cron trait
+ properties:
+ activeDeadlineSeconds:
+ description: |-
+ Specifies the duration in seconds, relative to the start time, that the job
+ may be continuously active before it is considered to be failed.
+ It defaults to 60s.
+ format: int64
+ type: integer
+ auto:
+ description: |-
+ Automatically deploy the integration as CronJob when all routes are
+ either starting from a periodic consumer (only `cron`, `timer` and `quartz` are supported) or a passive consumer (e.g. `direct` is a passive consumer).
+
+
+ It's required that all periodic consumers have the same period, and it can be expressed as cron schedule (e.g. `1m` can be expressed as `0/1 * * * *`,
+ while `35m` or `50s` cannot).
+ type: boolean
+ backoffLimit:
+ description: |-
+ Specifies the number of retries before marking the job failed.
+ It defaults to 2.
+ format: int32
+ type: integer
+ components:
+ description: |-
+ A comma separated list of the Camel components that need to be customized in order for them to work when the schedule is triggered externally by Kubernetes.
+ A specific customizer is activated for each specified component. E.g. for the `timer` component, the `cron-timer` customizer is
+ activated (it's present in the `org.apache.camel.k:camel-k-cron` library).
+
+
+ Supported components are currently: `cron`, `timer` and `quartz`.
+ type: string
+ concurrencyPolicy:
+ description: |-
+ Specifies how to treat concurrent executions of a Job.
+ Valid values are:
+ - "Allow": allows CronJobs to run concurrently;
+ - "Forbid" (default): forbids concurrent runs, skipping next run if previous run hasn't finished yet;
+ - "Replace": cancels currently running job and replaces it with a new one
+ enum:
+ - Allow
+ - Forbid
+ - Replace
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ fallback:
+ description: |-
+ Use the default Camel implementation of the `cron` endpoint (`quartz`) instead of trying to materialize the integration
+ as Kubernetes CronJob.
+ type: boolean
+ schedule:
+ description: |-
+ The CronJob schedule for the whole integration. If multiple routes are declared, they must have the same schedule for this
+ mechanism to work correctly.
+ type: string
+ startingDeadlineSeconds:
+ description: |-
+ Optional deadline in seconds for starting the job if it misses scheduled
+ time for any reason. Missed jobs executions will be counted as failed ones.
+ format: int64
+ type: integer
+ timeZone:
+ description: The timezone that the CronJob will run on
+ type: string
+ type: object
+ dependencies:
+ description: The configuration of Dependencies trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ type: object
+ deployer:
+ description: The configuration of Deployer trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ kind:
+ description: Allows to explicitly select the desired deployment
+ kind between `deployment`, `cron-job` or `knative-service`
+ when creating the resources for running the integration.
+ enum:
+ - deployment
+ - cron-job
+ - knative-service
+ type: string
+ useSSA:
+ description: |-
+ Deprecated: won't be able to enforce client side update in the future.
+ Use server-side apply to update the owned resources (default `true`).
+ Note that it automatically falls back to client-side patching, if SSA is not available, e.g., on old Kubernetes clusters.
+ type: boolean
+ type: object
+ deployment:
+ description: The configuration of Deployment trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ progressDeadlineSeconds:
+ description: |-
+ The maximum time in seconds for the deployment to make progress before it
+ is considered to be failed. It defaults to `60s`.
+ format: int32
+ type: integer
+ rollingUpdateMaxSurge:
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ The maximum number of pods that can be scheduled above the desired number of
+ pods.
+ Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ This can not be 0 if MaxUnavailable is 0.
+ Absolute number is calculated from percentage by rounding up.
+ Defaults to `25%`.
+ x-kubernetes-int-or-string: true
+ rollingUpdateMaxUnavailable:
+ anyOf:
+ - type: integer
+ - type: string
+ description: |-
+ The maximum number of pods that can be unavailable during the update.
+ Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
+ Absolute number is calculated from percentage by rounding down.
+ This can not be 0 if MaxSurge is 0.
+ Defaults to `25%`.
+ x-kubernetes-int-or-string: true
+ strategy:
+ description: The deployment strategy to use to replace existing
+ pods with new ones.
+ enum:
+ - Recreate
+ - RollingUpdate
+ type: string
+ type: object
+ environment:
+ description: The configuration of Environment trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ containerMeta:
+ description: Enables injection of `NAMESPACE` and `POD_NAME`
+ environment variables (default `true`)
+ type: boolean
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ httpProxy:
+ description: Propagates the `HTTP_PROXY`, `HTTPS_PROXY` and
+ `NO_PROXY` environment variables (default `true`)
+ type: boolean
+ vars:
+ description: |-
+ A list of environment variables to be added to the integration container.
+ The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
+ and key represents the resource key to be mapped as and environment variable.
+ These take precedence over any previously defined environment variables.
+ items:
+ type: string
+ type: array
+ type: object
+ error-handler:
+ description: The configuration of Error Handler trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ ref:
+ description: The error handler ref name provided or found
+ in application properties
+ type: string
+ type: object
+ gc:
+ description: The configuration of GC trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ discoveryCache:
+ description: |-
+ Discovery client cache to be used, either `disabled`, `disk` or `memory` (default `memory`).
+ Deprecated: to be removed from trait configuration.
+ enum:
+ - disabled
+ - disk
+ - memory
+ type: string
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ health:
+ description: The configuration of Health trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ livenessFailureThreshold:
+ description: Minimum consecutive failures for the liveness
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ livenessInitialDelay:
+ description: Number of seconds after the container has started
+ before the liveness probe is initiated.
+ format: int32
+ type: integer
+ livenessPeriod:
+ description: How often to perform the liveness probe.
+ format: int32
+ type: integer
+ livenessProbe:
+ description: The liveness probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ livenessProbeEnabled:
+ description: Configures the liveness probe for the integration
+ container (default `false`).
+ type: boolean
+ livenessScheme:
+ description: Scheme to use when connecting to the liveness
+ probe (default `HTTP`).
+ type: string
+ livenessSuccessThreshold:
+ description: Minimum consecutive successes for the liveness
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ livenessTimeout:
+ description: Number of seconds after which the liveness probe
+ times out.
+ format: int32
+ type: integer
+ readinessFailureThreshold:
+ description: Minimum consecutive failures for the readiness
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ readinessInitialDelay:
+ description: Number of seconds after the container has started
+ before the readiness probe is initiated.
+ format: int32
+ type: integer
+ readinessPeriod:
+ description: How often to perform the readiness probe.
+ format: int32
+ type: integer
+ readinessProbe:
+ description: The readiness probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ readinessProbeEnabled:
+ description: Configures the readiness probe for the integration
+ container (default `true`).
+ type: boolean
+ readinessScheme:
+ description: Scheme to use when connecting to the readiness
+ probe (default `HTTP`).
+ type: string
+ readinessSuccessThreshold:
+ description: Minimum consecutive successes for the readiness
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ readinessTimeout:
+ description: Number of seconds after which the readiness probe
+ times out.
+ format: int32
+ type: integer
+ startupFailureThreshold:
+ description: Minimum consecutive failures for the startup
+ probe to be considered failed after having succeeded.
+ format: int32
+ type: integer
+ startupInitialDelay:
+ description: Number of seconds after the container has started
+ before the startup probe is initiated.
+ format: int32
+ type: integer
+ startupPeriod:
+ description: How often to perform the startup probe.
+ format: int32
+ type: integer
+ startupProbe:
+ description: The startup probe path to use (default provided
+ by the Catalog runtime used).
+ type: string
+ startupProbeEnabled:
+ description: Configures the startup probe for the integration
+ container (default `false`).
+ type: boolean
+ startupScheme:
+ description: Scheme to use when connecting to the startup
+ probe (default `HTTP`).
+ type: string
+ startupSuccessThreshold:
+ description: Minimum consecutive successes for the startup
+ probe to be considered successful after having failed.
+ format: int32
+ type: integer
+ startupTimeout:
+ description: Number of seconds after which the startup probe
+ times out.
+ format: int32
+ type: integer
+ type: object
+ ingress:
+ description: The configuration of Ingress trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to the ingress.
+ This can be used to set controller specific annotations, e.g., when using the NGINX Ingress controller:
+ See https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md
+ type: object
+ auto:
+ description: To automatically add an ingress whenever the
+ integration uses an HTTP endpoint consumer.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ host:
+ description: To configure the host exposed by the ingress.
+ type: string
+ ingressClassName:
+ description: |-
+ The Ingress class name as defined by the Ingress spec
+ See https://kubernetes.io/docs/concepts/services-networking/ingress/
+ type: string
+ path:
+ description: To configure the path exposed by the ingress
+ (default `/`).
+ type: string
+ pathType:
+ description: |-
+ To configure the path type exposed by the ingress.
+ One of `Exact`, `Prefix`, `ImplementationSpecific` (default to `Prefix`).
+ enum:
+ - Exact
+ - Prefix
+ - ImplementationSpecific
+ type: string
+ tlsHosts:
+ description: To configure tls hosts
+ items:
+ type: string
+ type: array
+ tlsSecretName:
+ description: To configure tls secret name
+ type: string
+ type: object
+ istio:
+ description: The configuration of Istio trait
+ properties:
+ allow:
+ description: Configures a (comma-separated) list of CIDR subnets
+ that should not be intercepted by the Istio proxy (`10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`
+ by default).
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ inject:
+ description: Forces the value for labels `sidecar.istio.io/inject`.
+ By default the label is set to `true` on deployment and
+ not set on Knative Service.
+ type: boolean
+ type: object
+ jolokia:
+ description: The configuration of Jolokia trait
+ properties:
+ CACert:
+ description: |-
+ The PEM encoded CA certification file path, used to verify client certificates,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` for OpenShift).
+ type: string
+ clientPrincipal:
+ description: |-
+ The principal(s) which must be given in a client certificate to allow access to the Jolokia endpoint,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `clientPrincipal=cn=system:master-proxy`, `cn=hawtio-online.hawtio.svc` and `cn=fuse-console.fuse.svc` for OpenShift).
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ discoveryEnabled:
+ description: Listen for multicast requests (default `false`)
+ type: boolean
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ extendedClientCheck:
+ description: |-
+ Mandate the client certificate contains a client flag in the extended key usage section,
+ applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true`
+ (default `true` for OpenShift).
+ type: boolean
+ host:
+ description: |-
+ The Host address to which the Jolokia agent should bind to. If `"\*"` or `"0.0.0.0"` is given,
+ the servers binds to every network interface (default `"*"`).
+ type: string
+ options:
+ description: |-
+ A list of additional Jolokia options as defined
+ in https://jolokia.org/reference/html/agents.html#agent-jvm-config[JVM agent configuration options]
+ items:
+ type: string
+ type: array
+ password:
+ description: The password used for authentication, applicable
+ when the `user` option is set.
+ type: string
+ port:
+ description: The Jolokia endpoint port (default `8778`).
+ type: integer
+ protocol:
+ description: The protocol to use, either `http` or `https`
+ (default `https` for OpenShift)
+ type: string
+ useSSLClientAuthentication:
+ description: Whether client certificates should be used for
+ authentication (default `true` for OpenShift).
+ type: boolean
+ user:
+ description: The user to be used for authentication
+ type: string
+ type: object
+ jvm:
+ description: The configuration of JVM trait
+ properties:
+ classpath:
+ description: Additional JVM classpath (use `Linux` classpath
+ separator)
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ debug:
+ description: Activates remote debugging, so that a debugger
+ can be attached to the JVM, e.g., using port-forwarding
+ type: boolean
+ debugAddress:
+ description: Transport address at which to listen for the
+ newly launched JVM (default `*:5005`)
+ type: string
+ debugSuspend:
+ description: Suspends the target JVM immediately before the
+ main class is loaded
+ type: boolean
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ jar:
+ description: The Jar dependency which will run the application.
+ Leave it empty for managed Integrations.
+ type: string
+ options:
+ description: A list of JVM options
+ items:
+ type: string
+ type: array
+ printCommand:
+ description: |-
+ Prints the command used the start the JVM in the container logs (default `true`)
+ Deprecated: no longer in use.
+ type: boolean
+ type: object
+ kamelets:
+ description: The configuration of Kamelets trait
+ properties:
+ auto:
+ description: Automatically inject all referenced Kamelets
+ and their default configuration (enabled by default)
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ list:
+ description: Comma separated list of Kamelet names to load
+ into the current integration
+ type: string
+ mountPoint:
+ description: The directory where the application mounts and
+ reads Kamelet spec (default `/etc/camel/kamelets`)
+ type: string
+ type: object
+ keda:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ knative:
+ description: The configuration of Knative trait
+ properties:
+ auto:
+ description: Enable automatic discovery of all trait properties.
+ type: boolean
+ channelSinks:
+ description: |-
+ List of channels used as destination of integration routes.
+ Can contain simple channel names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ channelSources:
+ description: |-
+ List of channels used as source of integration routes.
+ Can contain simple channel names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ config:
+ description: Can be used to inject a Knative complete configuration
+ in JSON format.
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ endpointSinks:
+ description: |-
+ List of endpoints used as destination of integration routes.
+ Can contain simple endpoint names or full Camel URIs.
+ items:
+ type: string
+ type: array
+ endpointSources:
+ description: List of channels used as source of integration
+ routes.
+ items:
+ type: string
+ type: array
+ eventSinks:
+ description: |-
+ List of event types that the integration will produce.
+ Can contain simple event types or full Camel URIs (to use a specific broker).
+ items:
+ type: string
+ type: array
+ eventSources:
+ description: |-
+ List of event types that the integration will be subscribed to.
+ Can contain simple event types or full Camel URIs (to use a specific broker different from "default").
+ items:
+ type: string
+ type: array
+ filterEventType:
+ description: |-
+ Enables the default filtering for the Knative trigger using the event type
+ If this is true, the created Knative trigger uses the event type as a filter on the event stream when no other filter criteria is given. (default: true)
+ type: boolean
+ filterSourceChannels:
+ description: |-
+ Enables filtering on events based on the header "ce-knativehistory". Since this header has been removed in newer versions of
+ Knative, filtering is disabled by default.
+ type: boolean
+ filters:
+ description: |-
+ Sets filter attributes on the event stream (such as event type, source, subject and so on).
+ A list of key-value pairs that represent filter attributes and its values.
+ The syntax is KEY=VALUE, e.g., `source="my.source"`.
+ Filter attributes get set on the Knative trigger that is being created as part of this integration.
+ items:
+ type: string
+ type: array
+ namespaceLabel:
+ description: |-
+ Enables the camel-k-operator to set the "bindings.knative.dev/include=true" label to the namespace
+ As Knative requires this label to perform injection of K_SINK URL into the service.
+ If this is false, the integration pod may start and fail, read the SinkBinding Knative documentation. (default: true)
+ type: boolean
+ sinkBinding:
+ description: |-
+ Allows binding the integration to a sink via a Knative SinkBinding resource.
+ This can be used when the integration targets a single sink.
+ It's enabled by default when the integration targets a single sink
+ (except when the integration is owned by a Knative source).
+ type: boolean
+ type: object
+ knative-service:
+ description: The configuration of Knative Service trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to route.
+ This can be used to set knative service specific annotations
+ CLI usage example: -t "knative-service.annotations.'haproxy.router.openshift.io/balance'=true"
+ type: object
+ auto:
+ description: |-
+ Automatically deploy the integration as Knative service when all conditions hold:
+
+
+ * Integration is using the Knative profile
+ * All routes are either starting from an HTTP based consumer or a passive consumer (e.g. `direct` is a passive consumer)
+ type: boolean
+ autoscalingMetric:
+ description: |-
+ Configures the Knative autoscaling metric property (e.g. to set `concurrency` based or `cpu` based autoscaling).
+
+
+ Refer to the Knative documentation for more information.
+ type: string
+ autoscalingTarget:
+ description: |-
+ Sets the allowed concurrency level or CPU percentage (depending on the autoscaling metric) for each Pod.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ class:
+ description: |-
+ Configures the Knative autoscaling class property (e.g. to set `hpa.autoscaling.knative.dev` or `kpa.autoscaling.knative.dev` autoscaling).
+
+
+ Refer to the Knative documentation for more information.
+ enum:
+ - kpa.autoscaling.knative.dev
+ - hpa.autoscaling.knative.dev
+ type: string
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ maxScale:
+ description: |-
+ An upper bound for the number of Pods that can be running in parallel for the integration.
+ Knative has its own cap value that depends on the installation.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ minScale:
+ description: |-
+ The minimum number of Pods that should be running at any time for the integration. It's **zero** by default, meaning that
+ the integration is scaled down to zero when not used for a configured amount of time.
+
+
+ Refer to the Knative documentation for more information.
+ type: integer
+ rolloutDuration:
+ description: |-
+ Enables to gradually shift traffic to the latest Revision and sets the rollout duration.
+ It's disabled by default and must be expressed as a Golang `time.Duration` string representation,
+ rounded to a second precision.
+ type: string
+ timeoutSeconds:
+ description: |-
+ The maximum duration in seconds that the request instance is allowed to respond to a request.
+ This field propagates to the integration pod's terminationGracePeriodSeconds
+
+
+ Refer to the Knative documentation for more information.
+ format: int64
+ type: integer
+ visibility:
+ description: |-
+ Setting `cluster-local`, Knative service becomes a private service.
+ Specifically, this option applies the `networking.knative.dev/visibility` label to Knative service.
+
+
+ Refer to the Knative documentation for more information.
+ enum:
+ - cluster-local
+ type: string
+ type: object
+ logging:
+ description: The configuration of Logging trait
+ properties:
+ color:
+ description: Colorize the log output
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ format:
+ description: Logs message format
+ type: string
+ json:
+ description: Output the logs in JSON
+ type: boolean
+ jsonPrettyPrint:
+ description: Enable "pretty printing" of the JSON logs
+ type: boolean
+ level:
+ description: Adjust the logging level (defaults to `INFO`)
+ enum:
+ - FATAL
+ - WARN
+ - INFO
+ - DEBUG
+ - TRACE
+ type: string
+ type: object
+ master:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ mount:
+ description: The configuration of Mount trait
+ properties:
+ configs:
+ description: |-
+ A list of configuration pointing to configmap/secret.
+ The configuration are expected to be UTF-8 resources as they are processed by runtime Camel Context and tried to be parsed as property files.
+ They are also made available on the classpath in order to ease their usage directly from the Route.
+ Syntax: [configmap|secret]:name[/key], where name represents the resource name and key optionally represents the resource key to be filtered
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ emptyDirs:
+ description: 'A list of EmptyDir volumes to be mounted. Syntax:
+ [name:/container/path]'
+ items:
+ type: string
+ type: array
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ hotReload:
+ description: |-
+ Enable "hot reload" when a secret/configmap mounted is edited (default `false`). The configmap/secret must be
+ marked with `camel.apache.org/integration` label to be taken in account. The resource will be watched for any kind change, also for
+ changes in metadata.
+ type: boolean
+ resources:
+ description: |-
+ A list of resources (text or binary content) pointing to configmap/secret.
+ The resources are expected to be any resource type (text or binary content).
+ The destination path can be either a default location or any path specified by the user.
+ Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
+ items:
+ type: string
+ type: array
+ scanKameletsImplicitLabelSecrets:
+ description: 'Deprecated: no longer available since version
+ 2.5.'
+ type: boolean
+ volumes:
+ description: 'A list of Persistent Volume Claims to be mounted.
+ Syntax: [pvcname:/container/path]'
+ items:
+ type: string
+ type: array
+ type: object
+ openapi:
+ description: The configuration of OpenAPI trait
+ properties:
+ configmaps:
+ description: The configmaps holding the spec of the OpenAPI
+ (compatible with > 3.0 spec only).
+ items:
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ type: object
+ owner:
+ description: The configuration of Owner trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ targetAnnotations:
+ description: The set of annotations to be transferred
+ items:
+ type: string
+ type: array
+ targetLabels:
+ description: The set of labels to be transferred
+ items:
+ type: string
+ type: array
+ type: object
+ pdb:
+ description: The configuration of PDB trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ maxUnavailable:
+ description: |-
+ The number of pods for the Integration that can be unavailable after an eviction.
+ It can be either an absolute number or a percentage (default `1` if `min-available` is also not set).
+ Only one of `max-unavailable` and `min-available` can be specified.
+ type: string
+ minAvailable:
+ description: |-
+ The number of pods for the Integration that must still be available after an eviction.
+ It can be either an absolute number or a percentage.
+ Only one of `min-available` and `max-unavailable` can be specified.
+ type: string
+ type: object
+ platform:
+ description: The configuration of Platform trait
+ properties:
+ auto:
+ description: |-
+ To automatically detect from the environment if a default platform can be created (it will be created on OpenShift or when a registry address is set).
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ createDefault:
+ description: |-
+ To create a default (empty) platform when the platform is missing.
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ global:
+ description: |-
+ Indicates if the platform should be created globally in the case of global operator (default true).
+ Deprecated: Platform is auto generated by the operator install procedure - maintained for backward compatibility
+ type: boolean
+ type: object
+ pod:
+ description: The configuration of Pod trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ prometheus:
+ description: The configuration of Prometheus trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ podMonitor:
+ description: Whether a `PodMonitor` resource is created (default
+ `true`).
+ type: boolean
+ podMonitorLabels:
+ description: The `PodMonitor` resource labels, applicable
+ when `pod-monitor` is `true`.
+ items:
+ type: string
+ type: array
+ type: object
+ pull-secret:
+ description: The configuration of Pull Secret trait
+ properties:
+ auto:
+ description: Automatically configures the platform registry
+ secret on the pod if it is of type `kubernetes.io/dockerconfigjson`.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ imagePullerDelegation:
+ description: When using a global operator with a shared platform,
+ this enables delegation of the `system:image-puller` cluster
+ role on the operator namespace to the integration service
+ account.
+ type: boolean
+ secretName:
+ description: The pull secret name to set on the Pod. If left
+ empty this is automatically taken from the `IntegrationPlatform`
+ registry configuration.
+ type: string
+ type: object
+ quarkus:
+ description: The configuration of Quarkus trait
+ properties:
+ buildMode:
+ description: |-
+ The Quarkus mode to run: either `jvm` or `native` (default `jvm`).
+ In case both `jvm` and `native` are specified, two `IntegrationKit` resources are created,
+ with the `native` kit having precedence over the `jvm` one once ready.
+ items:
+ description: QuarkusMode is the type of Quarkus build packaging.
+ enum:
+ - jvm
+ - native
+ type: string
+ type: array
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ nativeBaseImage:
+ description: The base image to use when running a native build
+ (default `quay.io/quarkus/quarkus-micro-image:2.0`)
+ type: string
+ nativeBuilderImage:
+ description: The image containing the tooling required for
+ a native build (by default it will use the one provided
+ in the runtime catalog)
+ type: string
+ packageTypes:
+ description: |-
+ The Quarkus package types, `fast-jar` or `native` (default `fast-jar`).
+ In case both `fast-jar` and `native` are specified, two `IntegrationKit` resources are created,
+ with the native kit having precedence over the `fast-jar` one once ready.
+ The order influences the resolution of the current kit for the integration.
+ The kit corresponding to the first package type will be assigned to the
+ integration in case no existing kit that matches the integration exists.
+ Deprecated: use `build-mode` instead.
+ items:
+ description: |-
+ QuarkusPackageType is the type of Quarkus build packaging.
+ Deprecated: use `QuarkusMode` instead.
+ enum:
+ - fast-jar
+ - native
+ type: string
+ type: array
+ type: object
+ registry:
+ description: |-
+ The configuration of Registry trait (support removed since version 2.5.0).
+ Deprecated: use jvm trait or read documentation.
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ type: object
+ route:
+ description: The configuration of Route trait
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ description: |-
+ The annotations added to route.
+ This can be used to set route specific annotations
+ For annotations options see https://docs.openshift.com/container-platform/3.11/architecture/networking/routes.html#route-specific-annotations
+ CLI usage example: -t "route.annotations.'haproxy.router.openshift.io/balance'=true"
+ type: object
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ host:
+ description: To configure the host exposed by the route.
+ type: string
+ tlsCACertificate:
+ description: |-
+ The TLS CA certificate contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCACertificateSecret:
+ description: |-
+ The secret name and key reference to the TLS CA certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCertificate:
+ description: |-
+ The TLS certificate contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsCertificateSecret:
+ description: |-
+ The secret name and key reference to the TLS certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsDestinationCACertificate:
+ description: |-
+ The destination CA certificate provides the contents of the ca certificate of the final destination. When using reencrypt
+ termination this file should be provided in order to have routers use it for health checks on the secure connection.
+ If this field is not specified, the router may provide its own destination CA and perform hostname validation using
+ the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically
+ verify.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsDestinationCACertificateSecret:
+ description: |-
+ The secret name and key reference to the destination CA certificate. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsInsecureEdgeTerminationPolicy:
+ description: |-
+ To configure how to deal with insecure traffic, e.g. `Allow`, `Disable` or `Redirect` traffic.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ enum:
+ - None
+ - Allow
+ - Redirect
+ type: string
+ tlsKey:
+ description: |-
+ The TLS certificate key contents.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsKeySecret:
+ description: |-
+ The secret name and key reference to the TLS certificate key. The format is "secret-name[/key-name]", the value represents the secret name, if there is only one key in the secret it will be read, otherwise you can set a key name separated with a "/".
+
+
+ Refer to the OpenShift route documentation for additional information.
+ type: string
+ tlsTermination:
+ description: |-
+ The TLS termination type, like `edge`, `passthrough` or `reencrypt`.
+
+
+ Refer to the OpenShift route documentation for additional information.
+ enum:
+ - edge
+ - reencrypt
+ - passthrough
+ type: string
+ type: object
+ security-context:
+ description: The configuration of Security Context trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: 'Deprecated: no longer in use.'
+ type: boolean
+ runAsNonRoot:
+ description: Security Context RunAsNonRoot configuration (default
+ false).
+ type: boolean
+ runAsUser:
+ description: 'Security Context RunAsUser configuration (default
+ none): this value is automatically retrieved in Openshift
+ clusters when not explicitly set.'
+ format: int64
+ type: integer
+ seccompProfileType:
+ description: Security Context SeccompProfileType configuration
+ (default RuntimeDefault).
+ enum:
+ - Unconfined
+ - RuntimeDefault
+ type: string
+ type: object
+ service:
+ description: The configuration of Service trait
+ properties:
+ auto:
+ description: To automatically detect from the code if a Service
+ needs to be created.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ nodePort:
+ description: |-
+ Enable Service to be exposed as NodePort (default `false`).
+ Deprecated: Use service type instead.
+ type: boolean
+ type:
+ description: The type of service to be used, either 'ClusterIP',
+ 'NodePort' or 'LoadBalancer'.
+ enum:
+ - ClusterIP
+ - NodePort
+ - LoadBalancer
+ type: string
+ type: object
+ service-binding:
+ description: The configuration of Service Binding trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ services:
+ description: List of Services in the form [[apigroup/]version:]kind:[namespace/]name
+ items:
+ type: string
+ type: array
+ type: object
+ strimzi:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ telemetry:
+ description: The configuration of Telemetry trait
+ properties:
+ auto:
+ description: Enables automatic configuration of the trait,
+ including automatic discovery of the telemetry endpoint.
+ type: boolean
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ endpoint:
+ description: The target endpoint of the Telemetry service
+ (automatically discovered by default)
+ type: string
+ sampler:
+ description: The sampler of the telemetry used for tracing
+ (default "on")
+ type: string
+ sampler-parent-based:
+ description: The sampler of the telemetry used for tracing
+ is parent based (default "true")
+ type: boolean
+ sampler-ratio:
+ description: The sampler ratio of the telemetry used for tracing
+ type: string
+ serviceName:
+ description: The name of the service that publishes telemetry
+ data (defaults to the integration name)
+ type: string
+ type: object
+ toleration:
+ description: The configuration of Toleration trait
+ properties:
+ configuration:
+ description: |-
+ Legacy trait configuration parameters.
+ Deprecated: for backward compatibility.
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ enabled:
+ description: Can be used to enable or disable a trait. All
+ traits share this common property.
+ type: boolean
+ taints:
+ description: The list of taints to tolerate, in the form `Key[=Value]:Effect[:Seconds]`
+ items:
+ type: string
+ type: array
+ type: object
+ tracing:
+ description: 'Deprecated: for backward compatibility.'
+ properties:
+ configuration:
+ description: TraitConfiguration parameters configuration
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configuration
+ type: object
+ type: object
version:
description: the operator version
type: string
diff --git a/pkg/trait/affinity.go b/pkg/trait/affinity.go
index caa9278350..43f0485237 100644
--- a/pkg/trait/affinity.go
+++ b/pkg/trait/affinity.go
@@ -44,10 +44,6 @@ type affinityTrait struct {
func newAffinityTrait() Trait {
return &affinityTrait{
BaseTrait: NewBaseTrait(affinityTraitID, affinityTraitOrder),
- AffinityTrait: traitv1.AffinityTrait{
- PodAffinity: ptr.To(false),
- PodAntiAffinity: ptr.To(false),
- },
}
}
diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go
index a096c6e7c8..aaa30c00f7 100644
--- a/pkg/trait/builder_test.go
+++ b/pkg/trait/builder_test.go
@@ -67,10 +67,11 @@ func TestBuilderTraitNotAppliedBecauseOfNilPhase(t *testing.T) {
e.IntegrationKit.Status.Phase = v1.IntegrationKitPhaseInitialization
t.Run(string(e.Platform.Status.Cluster), func(t *testing.T) {
- conditions, err := NewBuilderTestCatalog().apply(e)
+ conditions, traits, err := NewBuilderTestCatalog().apply(e)
require.NoError(t, err)
assert.NotEmpty(t, conditions)
+ assert.Empty(t, traits)
assert.NotEmpty(t, e.ExecutedTraits)
assert.Nil(t, e.GetTrait("builder"))
assert.Empty(t, e.Pipeline)
@@ -80,9 +81,10 @@ func TestBuilderTraitNotAppliedBecauseOfNilPhase(t *testing.T) {
func TestS2IBuilderTrait(t *testing.T) {
env := createBuilderTestEnv(v1.IntegrationPlatformClusterOpenShift, v1.IntegrationPlatformBuildPublishStrategyS2I, v1.BuildStrategyRoutine)
- conditions, err := NewBuilderTestCatalog().apply(env)
+ conditions, traits, err := NewBuilderTestCatalog().apply(env)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
assert.NotNil(t, env.GetTrait("builder"))
@@ -97,9 +99,10 @@ func TestS2IBuilderTrait(t *testing.T) {
func TestJibBuilderTrait(t *testing.T) {
env := createBuilderTestEnv(v1.IntegrationPlatformClusterOpenShift, v1.IntegrationPlatformBuildPublishStrategyJib, v1.BuildStrategyRoutine)
- conditions, err := NewBuilderTestCatalog().apply(env)
+ conditions, traits, err := NewBuilderTestCatalog().apply(env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
assert.NotNil(t, env.GetTrait("builder"))
diff --git a/pkg/trait/camel.go b/pkg/trait/camel.go
index 698f360514..df94312aec 100644
--- a/pkg/trait/camel.go
+++ b/pkg/trait/camel.go
@@ -42,6 +42,8 @@ const (
type camelTrait struct {
BasePlatformTrait
traitv1.CamelTrait `property:",squash"`
+ // private configuration used only internally
+ runtimeVersion string
}
func newCamelTrait() Trait {
@@ -73,8 +75,10 @@ func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
if runtimeVersion, err := determineRuntimeVersion(e); err != nil {
return false, nil, err
} else {
- t.RuntimeVersion = runtimeVersion
+ t.runtimeVersion = runtimeVersion
}
+ } else {
+ t.runtimeVersion = t.RuntimeVersion
}
var cond *TraitCondition
@@ -89,7 +93,7 @@ func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
traitConfigurationReason,
fmt.Sprintf(
"Operated with CamelCatalog version %s which may be different from the runtime used in the container",
- t.RuntimeVersion,
+ t.runtimeVersion,
),
)
}
@@ -102,7 +106,7 @@ func (t *camelTrait) Apply(e *Environment) error {
// expects a CamelCatalog to be loaded regardless it's a managed or
// non managed build Integration
if e.CamelCatalog == nil {
- if err := t.loadOrCreateCatalog(e, t.RuntimeVersion); err != nil {
+ if err := t.loadOrCreateCatalog(e, t.runtimeVersion); err != nil {
return err
}
}
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 80c116991d..f3f24deb3b 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -66,20 +66,6 @@ type containerTrait struct {
func newContainerTrait() Trait {
return &containerTrait{
BasePlatformTrait: NewBasePlatformTrait(containerTraitID, containerTraitOrder),
- ContainerTrait: traitv1.ContainerTrait{
- Port: defaultContainerPort,
- ServicePort: defaultServicePort,
- ServicePortName: defaultContainerPortName,
- Name: defaultContainerName,
- RunAsNonRoot: ptr.To(defaultContainerRunAsNonRoot),
- SeccompProfileType: defaultContainerSeccompProfileType,
- AllowPrivilegeEscalation: ptr.To(defaultContainerAllowPrivilegeEscalation),
- CapabilitiesDrop: []corev1.Capability{defaultContainerCapabilitiesDrop},
- RequestCPU: defaultContainerResourceCPU,
- RequestMemory: defaultContainerResourceMemory,
- LimitCPU: defaultContainerLimitCPU,
- LimitMemory: defaultContainerLimitMemory,
- },
}
}
@@ -94,8 +80,9 @@ func (t *containerTrait) Configure(e *Environment) (bool, *TraitCondition, error
if ptr.Deref(t.Auto, true) {
if t.Expose == nil {
- e := e.Resources.GetServiceForIntegration(e.Integration) != nil
- t.Expose = &e
+ if e.Resources.GetServiceForIntegration(e.Integration) != nil {
+ t.Expose = ptr.To(true)
+ }
}
}
@@ -138,7 +125,7 @@ func (t *containerTrait) configureContainer(e *Environment) error {
e.ApplicationProperties = make(map[string]string)
}
container := corev1.Container{
- Name: t.Name,
+ Name: t.getContainerName(),
Image: e.Integration.Status.Image,
Env: make([]corev1.EnvVar, 0),
}
@@ -230,7 +217,7 @@ func (t *containerTrait) configureService(e *Environment, container *corev1.Cont
}
containerPort := corev1.ContainerPort{
Name: name,
- ContainerPort: int32(t.Port),
+ ContainerPort: int32(t.getPort()),
Protocol: corev1.ProtocolTCP,
}
if !isKnative {
@@ -238,8 +225,8 @@ func (t *containerTrait) configureService(e *Environment, container *corev1.Cont
service := e.Resources.GetServiceForIntegration(e.Integration)
if service != nil {
servicePort := corev1.ServicePort{
- Name: t.ServicePortName,
- Port: int32(t.ServicePort),
+ Name: t.getServicePortName(),
+ Port: int32(t.getServicePort()),
Protocol: corev1.ProtocolTCP,
TargetPort: intstr.FromString(name),
}
@@ -271,21 +258,21 @@ func (t *containerTrait) configureResources(container *corev1.Container) {
limitsList = make(corev1.ResourceList)
}
- requestsList, err = kubernetes.ConfigureResource(t.RequestCPU, requestsList, corev1.ResourceCPU)
+ requestsList, err = kubernetes.ConfigureResource(t.getRequestCPU(), requestsList, corev1.ResourceCPU)
if err != nil {
- t.L.Error(err, "unable to parse quantity", "request-cpu", t.RequestCPU)
+ t.L.Error(err, "unable to parse quantity", "request-cpu", t.getRequestCPU())
}
- requestsList, err = kubernetes.ConfigureResource(t.RequestMemory, requestsList, corev1.ResourceMemory)
+ requestsList, err = kubernetes.ConfigureResource(t.getRequestMemory(), requestsList, corev1.ResourceMemory)
if err != nil {
- t.L.Error(err, "unable to parse quantity", "request-memory", t.RequestMemory)
+ t.L.Error(err, "unable to parse quantity", "request-memory", t.getRequestMemory())
}
- limitsList, err = kubernetes.ConfigureResource(t.LimitCPU, limitsList, corev1.ResourceCPU)
+ limitsList, err = kubernetes.ConfigureResource(t.getLimitCPU(), limitsList, corev1.ResourceCPU)
if err != nil {
- t.L.Error(err, "unable to parse quantity", "limit-cpu", t.LimitCPU)
+ t.L.Error(err, "unable to parse quantity", "limit-cpu", t.getLimitCPU())
}
- limitsList, err = kubernetes.ConfigureResource(t.LimitMemory, limitsList, corev1.ResourceMemory)
+ limitsList, err = kubernetes.ConfigureResource(t.getLimitMemory(), limitsList, corev1.ResourceMemory)
if err != nil {
- t.L.Error(err, "unable to parse quantity", "limit-memory", t.LimitMemory)
+ t.L.Error(err, "unable to parse quantity", "limit-memory", t.getLimitMemory())
}
container.Resources.Requests = requestsList
@@ -300,12 +287,12 @@ func (t *containerTrait) configureCapabilities(e *Environment) {
func (t *containerTrait) setSecurityContext(e *Environment, container *corev1.Container) error {
sc := corev1.SecurityContext{
- RunAsNonRoot: t.RunAsNonRoot,
+ RunAsNonRoot: t.getRunAsNonRoot(),
SeccompProfile: &corev1.SeccompProfile{
- Type: t.SeccompProfileType,
+ Type: t.getSeccompProfileType(),
},
- AllowPrivilegeEscalation: t.AllowPrivilegeEscalation,
- Capabilities: &corev1.Capabilities{Drop: t.CapabilitiesDrop, Add: t.CapabilitiesAdd},
+ AllowPrivilegeEscalation: t.getAllowPrivilegeEscalation(),
+ Capabilities: &corev1.Capabilities{Drop: t.getCapabilitiesDrop(), Add: t.CapabilitiesAdd},
}
runAsUser, err := t.getUser(e)
@@ -342,3 +329,99 @@ func (t *containerTrait) getUser(e *Environment) (*int64, error) {
return runAsUser, nil
}
+
+func (t *containerTrait) getPort() int {
+ if t.Port == 0 {
+ return defaultContainerPort
+ }
+
+ return t.Port
+}
+
+func (t *containerTrait) getServicePort() int {
+ if t.ServicePort == 0 {
+ return defaultServicePort
+ }
+
+ return t.ServicePort
+}
+
+func (t *containerTrait) getServicePortName() string {
+ if t.ServicePortName == "" {
+ return defaultContainerPortName
+ }
+
+ return t.ServicePortName
+}
+
+func (t *containerTrait) getContainerName() string {
+ if t.Name == "" {
+ return defaultContainerName
+ }
+
+ return t.Name
+}
+
+func (t *containerTrait) getRunAsNonRoot() *bool {
+ if t.RunAsNonRoot == nil {
+ return ptr.To(defaultContainerRunAsNonRoot)
+ }
+
+ return t.RunAsNonRoot
+}
+
+func (t *containerTrait) getSeccompProfileType() corev1.SeccompProfileType {
+ if t.SeccompProfileType == "" {
+ return defaultContainerSeccompProfileType
+ }
+
+ return t.SeccompProfileType
+}
+
+func (t *containerTrait) getAllowPrivilegeEscalation() *bool {
+ if t.AllowPrivilegeEscalation == nil {
+ return ptr.To(defaultContainerAllowPrivilegeEscalation)
+ }
+
+ return t.AllowPrivilegeEscalation
+}
+
+func (t *containerTrait) getCapabilitiesDrop() []corev1.Capability {
+ if t.CapabilitiesDrop == nil {
+ return []corev1.Capability{defaultContainerCapabilitiesDrop}
+ }
+
+ return t.CapabilitiesDrop
+}
+
+func (t *containerTrait) getRequestCPU() string {
+ if t.RequestCPU == "" {
+ return defaultContainerResourceCPU
+ }
+
+ return t.RequestCPU
+}
+
+func (t *containerTrait) getRequestMemory() string {
+ if t.RequestMemory == "" {
+ return defaultContainerResourceMemory
+ }
+
+ return t.RequestMemory
+}
+
+func (t *containerTrait) getLimitCPU() string {
+ if t.LimitCPU == "" {
+ return defaultContainerLimitCPU
+ }
+
+ return t.LimitCPU
+}
+
+func (t *containerTrait) getLimitMemory() string {
+ if t.LimitMemory == "" {
+ return defaultContainerLimitMemory
+ }
+
+ return t.LimitMemory
+}
diff --git a/pkg/trait/container_probes_test.go b/pkg/trait/container_probes_test.go
index 4b128e9c2a..0d17162a3b 100644
--- a/pkg/trait/container_probes_test.go
+++ b/pkg/trait/container_probes_test.go
@@ -80,8 +80,9 @@ func TestProbesDependencies(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseInitialization
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Contains(t, env.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus:camel-quarkus-microprofile-health")
}
@@ -105,8 +106,9 @@ func TestProbesOnDeployment(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
container := env.GetIntegrationContainer()
@@ -143,8 +145,9 @@ func TestProbesOnDeploymentWithCustomScheme(t *testing.T) {
env := newTestProbesEnv(t, integration)
env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
container := env.GetIntegrationContainer()
@@ -200,8 +203,9 @@ func TestProbesOnKnativeService(t *testing.T) {
"controller strategy: knative-service",
)
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, ctrlStrategyCondition)
assert.Contains(t, conditions, serviceOverrideCondition)
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index db41467a84..ff52d6e8b5 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -86,9 +86,10 @@ func TestContainerWithDefaults(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -167,9 +168,10 @@ func TestContainerWithOpenshift(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -235,9 +237,10 @@ func TestContainerWithCustomName(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -301,9 +304,10 @@ func TestContainerWithCustomImage(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
for _, postAction := range environment.PostActions {
@@ -370,8 +374,9 @@ func TestContainerWithCustomImageAndIntegrationKit(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.Error(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.Contains(t, err.Error(), "unsupported configuration: a container image has been set in conjunction with an IntegrationKit")
}
@@ -414,9 +419,10 @@ func TestContainerWithImagePullPolicy(t *testing.T) {
environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
container := environment.GetIntegrationContainer()
@@ -479,7 +485,7 @@ func TestDeploymentContainerPorts(t *testing.T) {
environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
container := environment.GetIntegrationContainer()
assert.Len(t, container.Ports, 1)
@@ -545,7 +551,7 @@ func TestKnativeServiceContainerPorts(t *testing.T) {
environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
container := environment.GetIntegrationContainer()
assert.Len(t, container.Ports, 1)
@@ -557,9 +563,10 @@ func TestDefaultKubernetesSecurityContext(t *testing.T) {
environment := createSettingContextEnvironment(t, v1.TraitProfileKubernetes)
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -587,9 +594,10 @@ func TestDefaultKnativeSecurityContext(t *testing.T) {
}
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("deployment"))
@@ -625,9 +633,10 @@ func TestUserSecurityContext(t *testing.T) {
}
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -648,9 +657,10 @@ func TestUserSecurityContext(t *testing.T) {
func TestUserDefaultResources(t *testing.T) {
environment := createSettingContextEnvironment(t, v1.TraitProfileKubernetes)
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index 7fbb35d9ea..80da757783 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -88,15 +88,6 @@ func (t *cronTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() {
return false, nil, nil
}
- if _, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityCron]; !ok {
- return false, NewIntegrationCondition(
- "Cron",
- v1.IntegrationConditionCronJobAvailable,
- corev1.ConditionFalse,
- v1.IntegrationConditionCronJobNotAvailableReason,
- "the runtime provider %s does not declare 'cron' capability",
- ), nil
- }
if ptr.Deref(t.Auto, true) {
err := t.autoConfigure(e)
@@ -143,7 +134,11 @@ func (t *cronTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
return false, nil, nil
}
- return t.Schedule != "", nil, nil
+ if t.Schedule != "" {
+ t.Enabled = ptr.To(true)
+ }
+
+ return ptr.Deref(t.Enabled, false), nil, nil
}
func (t *cronTrait) autoConfigure(e *Environment) error {
@@ -164,10 +159,6 @@ func (t *cronTrait) autoConfigure(e *Environment) error {
t.Components = strings.Join(configuredComponents, ",")
}
- if t.ConcurrencyPolicy == "" {
- t.ConcurrencyPolicy = string(batchv1.ForbidConcurrent)
- }
-
if (t.Schedule == "" && t.Components == "") && t.Fallback == nil {
// If there's at least a `cron` endpoint, add a fallback implementation
fromURIs, err := t.getSourcesFromURIs(e)
@@ -254,7 +245,7 @@ func (t *cronTrait) getCronJobFor(e *Environment) *batchv1.CronJob {
Spec: batchv1.CronJobSpec{
Schedule: t.Schedule,
TimeZone: t.TimeZone,
- ConcurrencyPolicy: batchv1.ConcurrencyPolicy(t.ConcurrencyPolicy),
+ ConcurrencyPolicy: t.getConcurrentPolicy(),
StartingDeadlineSeconds: t.StartingDeadlineSeconds,
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
@@ -361,6 +352,14 @@ func (t *cronTrait) getSourcesFromURIs(e *Environment) ([]string, error) {
return fromUris, nil
}
+func (t *cronTrait) getConcurrentPolicy() batchv1.ConcurrencyPolicy {
+ if t.ConcurrencyPolicy == "" {
+ return batchv1.ForbidConcurrent
+ }
+
+ return batchv1.ConcurrencyPolicy(t.ConcurrencyPolicy)
+}
+
func getCronForURIs(camelURIs []string) *cronInfo {
var globalCron *cronInfo
for _, camelURI := range camelURIs {
diff --git a/pkg/trait/cron_test.go b/pkg/trait/cron_test.go
index 178f22d082..e09eaeff21 100644
--- a/pkg/trait/cron_test.go
+++ b/pkg/trait/cron_test.go
@@ -285,9 +285,10 @@ func TestCronDeps(t *testing.T) {
require.NoError(t, err)
tc := NewCatalog(c)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -367,9 +368,10 @@ func TestCronMultipleScheduleFallback(t *testing.T) {
assert.Nil(t, err)
tc := NewCatalog(c)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
assert.Nil(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -445,9 +447,10 @@ func TestCronDepsFallback(t *testing.T) {
tc := NewCatalog(c)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -528,8 +531,9 @@ func TestCronWithActiveDeadline(t *testing.T) {
"DeploymentAvailable",
"controller strategy: cron-job",
)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -617,8 +621,9 @@ func TestCronWithBackoffLimit(t *testing.T) {
"DeploymentAvailable",
"controller strategy: cron-job",
)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -710,8 +715,9 @@ func TestCronWithTimeZone(t *testing.T) {
"DeploymentAvailable",
"controller strategy: cron-job",
)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -726,3 +732,72 @@ func TestCronWithTimeZone(t *testing.T) {
assert.NotNil(t, cronJob.Spec.TimeZone)
assert.EqualValues(t, *cronJob.Spec.TimeZone, "America/Sao_Paulo")
}
+
+func TestCronAuto(t *testing.T) {
+ catalog, err := camel.DefaultCatalog()
+ require.NoError(t, err)
+
+ client, _ := test.NewFakeClient()
+ traitCatalog := NewCatalog(nil)
+
+ environment := 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: `from("cron:tab?schedule=0 0/2 * * ?").to("log:test")`,
+ },
+ Language: v1.LanguageJavaSource,
+ },
+ },
+ },
+ },
+ IntegrationKit: &v1.IntegrationKit{
+ Status: v1.IntegrationKitStatus{
+ Phase: v1.IntegrationKitPhaseReady,
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ Spec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ RuntimeVersion: catalog.Runtime.Version,
+ },
+ },
+ Status: v1.IntegrationPlatformStatus{
+ Phase: v1.IntegrationPlatformPhaseReady,
+ },
+ },
+ EnvVars: make([]corev1.EnvVar, 0),
+ ExecutedTraits: make([]Trait, 0),
+ Resources: kubernetes.NewCollection(),
+ }
+ environment.Platform.ResyncStatusFullConfig()
+
+ c, err := NewFakeClient("ns")
+ require.NoError(t, err)
+
+ tc := NewCatalog(c)
+ _, traits, err := tc.apply(&environment)
+ require.NoError(t, err)
+ assert.NotEmpty(t, traits)
+
+ assert.Equal(t, &traitv1.CronTrait{
+ Trait: traitv1.Trait{
+ Enabled: ptr.To(true),
+ },
+ Schedule: "0 0/2 * * ?",
+ Components: "cron",
+ }, traits.Cron)
+}
diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go
index c1db2aec84..da49b26f76 100644
--- a/pkg/trait/environment.go
+++ b/pkg/trait/environment.go
@@ -59,9 +59,6 @@ const (
func newEnvironmentTrait() Trait {
return &environmentTrait{
BasePlatformTrait: NewBasePlatformTrait(environmentTraitID, environmentTraitOrder),
- EnvironmentTrait: traitv1.EnvironmentTrait{
- ContainerMeta: ptr.To(true),
- },
}
}
diff --git a/pkg/trait/environment_test.go b/pkg/trait/environment_test.go
index 05bf6cd8e6..d7ffdf0c84 100644
--- a/pkg/trait/environment_test.go
+++ b/pkg/trait/environment_test.go
@@ -43,8 +43,9 @@ func TestDefaultEnvironment(t *testing.T) {
env := mockEnvironment(catalog)
env.Platform.ResyncStatusFullConfig()
- conditions, err := NewEnvironmentTestCatalog().apply(&env)
+ conditions, traits, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
ns := false
@@ -92,8 +93,9 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) {
}
env.Platform.ResyncStatusFullConfig()
- conditions, err := NewEnvironmentTestCatalog().apply(&env)
+ conditions, traits, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
ns := false
@@ -132,8 +134,9 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) {
env.Platform.ResyncStatusFullConfig()
- conditions, err := NewEnvironmentTestCatalog().apply(&env)
+ conditions, traits, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
ns := false
@@ -171,8 +174,9 @@ func TestCustomEnvVars(t *testing.T) {
}
env.Platform.ResyncStatusFullConfig()
- conditions, err := NewEnvironmentTestCatalog().apply(&env)
+ conditions, traits, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
userK1 := false
@@ -205,8 +209,9 @@ func TestValueSourceEnvVars(t *testing.T) {
}
env.Platform.ResyncStatusFullConfig()
- conditions, err := NewEnvironmentTestCatalog().apply(&env)
+ conditions, traits, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
userK1 := false
diff --git a/pkg/trait/health.go b/pkg/trait/health.go
index 98d87b046d..fe4e4bc0dd 100644
--- a/pkg/trait/health.go
+++ b/pkg/trait/health.go
@@ -47,11 +47,6 @@ type healthTrait struct {
func newHealthTrait() Trait {
return &healthTrait{
BaseTrait: NewBaseTrait(healthTraitID, healthTraitOrder),
- HealthTrait: traitv1.HealthTrait{
- LivenessScheme: string(corev1.URISchemeHTTP),
- ReadinessScheme: string(corev1.URISchemeHTTP),
- StartupScheme: string(corev1.URISchemeHTTP),
- },
}
}
@@ -156,12 +151,36 @@ func (t *healthTrait) setProbes(container *corev1.Container, port *intstr.IntOrS
return nil
}
+func (t *healthTrait) getLivenessScheme() corev1.URIScheme {
+ if t.LivenessScheme == "" {
+ return corev1.URISchemeHTTP
+ }
+
+ return corev1.URIScheme(t.LivenessScheme)
+}
+
+func (t *healthTrait) getReadinessScheme() corev1.URIScheme {
+ if t.ReadinessScheme == "" {
+ return corev1.URISchemeHTTP
+ }
+
+ return corev1.URIScheme(t.ReadinessScheme)
+}
+
+func (t *healthTrait) getStartupScheme() corev1.URIScheme {
+ if t.StartupScheme == "" {
+ return corev1.URISchemeHTTP
+ }
+
+ return corev1.URIScheme(t.StartupScheme)
+}
+
func (t *healthTrait) newLivenessProbe(port *intstr.IntOrString, path string) *corev1.Probe {
p := corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: path,
- Scheme: corev1.URIScheme(t.LivenessScheme),
+ Scheme: t.getLivenessScheme(),
},
},
InitialDelaySeconds: t.LivenessInitialDelay,
@@ -183,7 +202,7 @@ func (t *healthTrait) newReadinessProbe(port *intstr.IntOrString, path string) *
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: path,
- Scheme: corev1.URIScheme(t.ReadinessScheme),
+ Scheme: t.getReadinessScheme(),
},
},
InitialDelaySeconds: t.ReadinessInitialDelay,
@@ -205,7 +224,7 @@ func (t *healthTrait) newStartupProbe(port *intstr.IntOrString, path string) *co
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: path,
- Scheme: corev1.URIScheme(t.StartupScheme),
+ Scheme: t.getStartupScheme(),
},
},
InitialDelaySeconds: t.StartupInitialDelay,
diff --git a/pkg/trait/health_test.go b/pkg/trait/health_test.go
index e60e8fd150..c9092ef6b4 100644
--- a/pkg/trait/health_test.go
+++ b/pkg/trait/health_test.go
@@ -90,7 +90,7 @@ func TestHealthTrait(t *testing.T) {
Resources: kubernetes.NewCollection(),
}
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
d := environment.Resources.GetDeploymentForIntegration(environment.Integration)
@@ -108,7 +108,7 @@ func TestHealthTrait(t *testing.T) {
environment.Integration.Spec.Traits.Health.StartupProbeEnabled = ptr.To(true)
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
d = environment.Resources.GetDeploymentForIntegration(environment.Integration)
assert.NotNil(t, d)
diff --git a/pkg/trait/ingress.go b/pkg/trait/ingress.go
index 6ee6a4c1d8..d78a6248e6 100644
--- a/pkg/trait/ingress.go
+++ b/pkg/trait/ingress.go
@@ -32,6 +32,9 @@ import (
const (
ingressTraitID = "ingress"
ingressTraitOrder = 2400
+
+ defaultPath = "/"
+ defaultPathTypePrefix = networkingv1.PathTypePrefix
)
type ingressTrait struct {
@@ -42,15 +45,6 @@ type ingressTrait struct {
func newIngressTrait() Trait {
return &ingressTrait{
BaseTrait: NewBaseTrait(ingressTraitID, ingressTraitOrder),
- IngressTrait: traitv1.IngressTrait{
- IngressClassName: "",
- Annotations: map[string]string{},
- Host: "",
- Path: "/",
- PathType: ptrFrom(networkingv1.PathTypePrefix),
- TLSHosts: []string{},
- TLSSecretName: "",
- },
}
}
@@ -88,7 +82,7 @@ func (t *ingressTrait) Configure(e *Environment) (bool, *TraitCondition, error)
func (t *ingressTrait) Apply(e *Environment) error {
service := e.Resources.GetUserServiceForIntegration(e.Integration)
if service == nil {
- return errors.New("cannot Apply ingress trait: no target service")
+ return errors.New("cannot apply ingress trait: no target service")
}
ingress := networkingv1.Ingress{
@@ -109,8 +103,8 @@ func (t *ingressTrait) Apply(e *Environment) error {
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
- Path: t.Path,
- PathType: t.PathType,
+ Path: t.getPath(),
+ PathType: t.getPathType(),
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: service.Name,
@@ -153,3 +147,19 @@ func (t *ingressTrait) Apply(e *Environment) error {
return nil
}
+
+func (t *ingressTrait) getPath() string {
+ if t.Path == "" {
+ return defaultPath
+ }
+
+ return t.Path
+}
+
+func (t *ingressTrait) getPathType() *networkingv1.PathType {
+ if t.PathType == nil {
+ return ptr.To(defaultPathTypePrefix)
+ }
+
+ return t.PathType
+}
diff --git a/pkg/trait/ingress_test.go b/pkg/trait/ingress_test.go
index d07aa57ba6..6635bd1249 100644
--- a/pkg/trait/ingress_test.go
+++ b/pkg/trait/ingress_test.go
@@ -95,7 +95,7 @@ func TestApplyIngressTraitWithoutUserServiceDoesNotSucceed(t *testing.T) {
err := ingressTrait.Apply(environment)
require.Error(t, err)
- assert.Equal(t, "cannot Apply ingress trait: no target service", err.Error())
+ assert.Equal(t, "cannot apply ingress trait: no target service", err.Error())
assert.Len(t, environment.Resources.Items(), 0)
}
diff --git a/pkg/trait/istio.go b/pkg/trait/istio.go
index 93169ddbc1..b61a4d1dd5 100644
--- a/pkg/trait/istio.go
+++ b/pkg/trait/istio.go
@@ -43,14 +43,13 @@ type istioTrait struct {
const (
istioSidecarInjectAnnotation = "sidecar.istio.io/inject"
istioOutboundIPRangesAnnotation = "traffic.sidecar.istio.io/includeOutboundIPRanges"
+
+ defaultAllow = "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
)
func newIstioTrait() Trait {
return &istioTrait{
BaseTrait: NewBaseTrait(istioTraitID, istioTraitOrder),
- IstioTrait: traitv1.IstioTrait{
- Allow: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16",
- },
}
}
@@ -63,7 +62,7 @@ func (t *istioTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
}
func (t *istioTrait) Apply(e *Environment) error {
- if t.Allow != "" {
+ if t.getAllow() != "" {
e.Resources.VisitDeployment(func(d *appsv1.Deployment) {
d.Spec.Template.Annotations = t.injectIstioAnnotation(d.Spec.Template.Annotations, true)
})
@@ -78,7 +77,7 @@ func (t *istioTrait) injectIstioAnnotation(annotations map[string]string, includ
if annotations == nil {
annotations = make(map[string]string)
}
- annotations[istioOutboundIPRangesAnnotation] = t.Allow
+ annotations[istioOutboundIPRangesAnnotation] = t.getAllow()
if includeInject {
annotations[istioSidecarInjectAnnotation] = boolean.TrueString
}
@@ -87,3 +86,11 @@ func (t *istioTrait) injectIstioAnnotation(annotations map[string]string, includ
}
return annotations
}
+
+func (t *istioTrait) getAllow() string {
+ if t.Allow == "" {
+ return defaultAllow
+ }
+
+ return t.Allow
+}
diff --git a/pkg/trait/istio_test.go b/pkg/trait/istio_test.go
index e6f63df4c5..13d2369e23 100644
--- a/pkg/trait/istio_test.go
+++ b/pkg/trait/istio_test.go
@@ -102,8 +102,9 @@ func TestIstioInject(t *testing.T) {
}
env := NewIstioTestEnv(t, &d, &s, true)
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Empty(t, s.Spec.ConfigurationSpec.Template.Annotations[istioSidecarInjectAnnotation])
assert.NotEmpty(t, d.Spec.Template.Annotations[istioSidecarInjectAnnotation])
@@ -127,8 +128,9 @@ func TestIstioForcedInjectTrue(t *testing.T) {
env.Integration.Spec.Traits.Istio.Enabled = ptr.To(true)
env.Integration.Spec.Traits.Istio.Inject = ptr.To(true)
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Equal(t, boolean.TrueString, s.Spec.ConfigurationSpec.Template.Annotations[istioSidecarInjectAnnotation])
assert.Equal(t, boolean.TrueString, d.Spec.Template.Annotations[istioSidecarInjectAnnotation])
@@ -152,8 +154,9 @@ func TestIstioForcedInjectFalse(t *testing.T) {
env.Integration.Spec.Traits.Istio.Enabled = ptr.To(true)
env.Integration.Spec.Traits.Istio.Inject = ptr.To(false)
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Equal(t, boolean.FalseString, s.Spec.ConfigurationSpec.Template.Annotations[istioSidecarInjectAnnotation])
assert.Equal(t, boolean.FalseString, d.Spec.Template.Annotations[istioSidecarInjectAnnotation])
@@ -175,8 +178,9 @@ func TestIstioDisabled(t *testing.T) {
env := NewIstioTestEnv(t, &d, &s, false)
- conditions, err := env.Catalog.apply(&env)
+ conditions, traits, err := env.Catalog.apply(&env)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotContains(t, env.ExecutedTraits, "istio")
}
diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go
index d5f602ea66..cf4dc6959e 100644
--- a/pkg/trait/jolokia.go
+++ b/pkg/trait/jolokia.go
@@ -45,9 +45,6 @@ type jolokiaTrait struct {
func newJolokiaTrait() Trait {
return &jolokiaTrait{
BaseTrait: NewBaseTrait(jolokiaTraitID, jolokiaTraitOrder),
- JolokiaTrait: traitv1.JolokiaTrait{
- Port: defaultJolokiaPort,
- },
}
}
@@ -107,7 +104,7 @@ func (t *jolokiaTrait) Apply(e *Environment) error {
t.addToJolokiaOptions(options, "extendedClientCheck", t.ExtendedClientCheck)
t.addToJolokiaOptions(options, "host", t.Host)
t.addToJolokiaOptions(options, "password", t.Password)
- t.addToJolokiaOptions(options, "port", t.Port)
+ t.addToJolokiaOptions(options, "port", t.getPort())
t.addToJolokiaOptions(options, "protocol", t.Protocol)
t.addToJolokiaOptions(options, "user", t.User)
t.addToJolokiaOptions(options, "useSslClientAuthentication", t.UseSslClientAuthentication)
@@ -131,7 +128,7 @@ func (t *jolokiaTrait) Apply(e *Environment) error {
containerPort := corev1.ContainerPort{
Name: "jolokia",
- ContainerPort: int32(t.Port),
+ ContainerPort: int32(t.getPort()),
Protocol: corev1.ProtocolTCP,
}
@@ -147,6 +144,14 @@ func (t *jolokiaTrait) Apply(e *Environment) error {
return nil
}
+func (t *jolokiaTrait) getPort() int {
+ if t.Port == 0 {
+ return defaultJolokiaPort
+ }
+
+ return t.Port
+}
+
func (t *jolokiaTrait) setDefaultJolokiaOption(options map[string]string, option interface{}, key string, value interface{}) {
// Do not override existing option
if _, ok := options[key]; ok {
diff --git a/pkg/trait/jolokia_test.go b/pkg/trait/jolokia_test.go
index b9ffa492b2..cf9b06fdf0 100644
--- a/pkg/trait/jolokia_test.go
+++ b/pkg/trait/jolokia_test.go
@@ -53,10 +53,11 @@ func TestApplyJolokiaTraitNominalShouldSucceed(t *testing.T) {
container := environment.Resources.GetContainerByName(defaultContainerName)
assert.NotNil(t, container)
- assert.Equal(t, container.Args, []string{
+ assert.Equal(t, []string{
"-javaagent:dependencies/lib/main/org.jolokia.jolokia-agent-jvm-1.7.1.jar=discoveryEnabled=false,host=*,port=8778",
"-cp", "dependencies/lib/main/org.jolokia.jolokia-agent-jvm-1.7.1.jar",
- })
+ },
+ container.Args)
assert.Len(t, container.Ports, 1)
containerPort := container.Ports[0]
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 0a28ba036d..096d315308 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -57,9 +57,6 @@ type jvmTrait struct {
func newJvmTrait() Trait {
return &jvmTrait{
BaseTrait: NewBaseTrait(jvmTraitID, jvmTraitOrder),
- JVMTrait: traitv1.JVMTrait{
- DebugAddress: "*:5005",
- },
}
}
@@ -230,6 +227,7 @@ func (t *jvmTrait) enableDebug(e *Environment) string {
}
meta.Labels["camel.apache.org/debug"] = "true"
})
+ t.DebugAddress = "*:5005"
return fmt.Sprintf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=%s,address=%s",
suspend, t.DebugAddress)
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index fd764264b6..328b432664 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -48,8 +48,6 @@ const (
contentKey = "content"
KameletLocationProperty = "camel.component.kamelet.location"
- kameletLabel = "camel.apache.org/kamelet"
- kameletConfigurationLabel = "camel.apache.org/kamelet.configuration"
kameletMountPointAnnotation = "camel.apache.org/kamelet.mount-point"
)
@@ -76,9 +74,6 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, *TraitCondition, error)
if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() {
return false, nil, nil
}
- if t.MountPoint == "" {
- t.MountPoint = filepath.Join(camel.BasePath, "kamelets")
- }
if ptr.Deref(t.Auto, true) {
var kamelets []string
_, err := e.ConsumeMeta(func(meta metadata.IntegrationMetadata) bool {
@@ -223,7 +218,7 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
e.ApplicationProperties = map[string]string{}
}
for _, cm := range bundleConfigmaps {
- kameletMountPoint := fmt.Sprintf("%s/%s", t.MountPoint, cm.Name)
+ kameletMountPoint := fmt.Sprintf("%s/%s", t.getMountPoint(), cm.Name)
cm.Annotations[kameletMountPointAnnotation] = kameletMountPoint
e.Resources.Add(cm)
if e.ApplicationProperties[KameletLocationProperty] == "" {
@@ -300,6 +295,14 @@ func (t *kameletsTrait) getKameletKeys(withVersion bool) []string {
return answer
}
+func (t *kameletsTrait) getMountPoint() string {
+ if t.MountPoint == "" {
+ return filepath.Join(camel.BasePath, "kamelets")
+ }
+
+ return t.MountPoint
+}
+
func getKameletKey(item string, withVersion bool) string {
i := strings.Trim(item, " \t\"")
if strings.Contains(i, "/") {
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index ac7ad9411c..2b43d40afa 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -22,6 +22,7 @@ import (
"testing"
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/util/camel"
"github.com/apache/camel-k/v2/pkg/util/kubernetes"
@@ -695,3 +696,55 @@ func TestKameletSyntheticKitAutoConditionFalse(t *testing.T) {
})
assert.Nil(t, kameletsBundle)
}
+
+func TestKameletAuto(t *testing.T) {
+ flow := `
+- from:
+ uri: kamelet:timer
+ steps:
+ - to: kamelet:none
+`
+ trait, environment := createKameletsTestEnvironment(
+ flow,
+ &v1.Kamelet{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "timer",
+ },
+ Spec: v1.KameletSpec{
+ KameletSpecBase: v1.KameletSpecBase{
+ Template: templateOrFail(map[string]interface{}{
+ "from": map[string]interface{}{
+ "uri": "timer:tick",
+ },
+ }),
+ },
+ },
+ },
+ &v1.Kamelet{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "none",
+ },
+ Spec: v1.KameletSpec{
+ KameletSpecBase: v1.KameletSpecBase{
+ Template: templateOrFail(map[string]interface{}{
+ "from": map[string]interface{}{
+ "uri": "timer:tick",
+ },
+ }),
+ },
+ },
+ })
+
+ enabled, condition, err := trait.Configure(environment)
+ require.NoError(t, err)
+ assert.True(t, enabled)
+ assert.Nil(t, condition)
+
+ err = trait.Apply(environment)
+ require.NoError(t, err)
+ assert.Equal(t, traitv1.KameletsTrait{
+ List: "none,timer",
+ }, trait.KameletsTrait)
+}
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index 9f52337284..19439453d3 100644
--- a/pkg/trait/knative.go
+++ b/pkg/trait/knative.go
@@ -80,25 +80,7 @@ func (t *knativeTrait) Configure(e *Environment) (bool, *TraitCondition, error)
return false, nil, nil
}
- knativeInstalled, err := knativeutil.IsEventingInstalled(e.Client)
- if err != nil {
- return false, nil, err
- }
-
- if !ptr.Deref(t.Auto, true) {
- if !knativeInstalled {
- return false, NewIntegrationCondition(
- "Knative",
- v1.IntegrationConditionKnativeAvailable,
- corev1.ConditionFalse,
- v1.IntegrationConditionKnativeNotInstalledReason,
- "integration cannot run. Knative is not installed in the cluster",
- ), fmt.Errorf("integration cannot run. Knative is not installed in the cluster")
- }
- return true, nil, nil
- }
-
- _, err = e.ConsumeMeta(func(meta metadata.IntegrationMetadata) bool {
+ _, err := e.ConsumeMeta(func(meta metadata.IntegrationMetadata) bool {
if len(t.ChannelSources) == 0 {
t.ChannelSources = filterMetaItems(meta, knativeapi.CamelServiceTypeChannel, "from")
}
@@ -123,30 +105,37 @@ func (t *knativeTrait) Configure(e *Environment) (bool, *TraitCondition, error)
return false, nil, err
}
- hasKnativeEndpoint := len(t.ChannelSources) > 0 || len(t.ChannelSinks) > 0 || len(t.EndpointSources) > 0 || len(t.EndpointSinks) > 0 || len(t.EventSources) > 0 || len(t.EventSinks) > 0
-
- if !hasKnativeEndpoint && !ptr.Deref(t.Enabled, false) {
- return false, nil, nil
- }
- if !knativeInstalled {
- return false, NewIntegrationCondition(
- "Knative",
- v1.IntegrationConditionKnativeAvailable,
- corev1.ConditionFalse,
- v1.IntegrationConditionKnativeNotInstalledReason,
- "integration cannot run. Knative is not installed in the cluster",
- ), fmt.Errorf("integration cannot run. Knative is not installed in the cluster")
+ if t.Enabled == nil {
+ // If the trait is enabled, then, we can skip this optimization
+ hasKnativeEndpoint := len(t.ChannelSources) > 0 || len(t.ChannelSinks) > 0 ||
+ len(t.EndpointSources) > 0 || len(t.EndpointSinks) > 0 ||
+ len(t.EventSources) > 0 || len(t.EventSinks) > 0
+ t.Enabled = ptr.To(hasKnativeEndpoint)
}
- if t.FilterSourceChannels == nil {
- // Filtering is no longer used by default
- t.FilterSourceChannels = ptr.To(false)
- }
- if t.SinkBinding == nil {
- allowed := t.isSinkBindingAllowed(e)
- t.SinkBinding = &allowed
+
+ if ptr.Deref(t.Enabled, false) {
+ // Verify if Knative eventing is installed
+ knativeInstalled, err := knativeutil.IsEventingInstalled(e.Client)
+ if err != nil {
+ return false, nil, err
+ }
+ if !knativeInstalled {
+ return false, NewIntegrationCondition(
+ "Knative",
+ v1.IntegrationConditionKnativeAvailable,
+ corev1.ConditionFalse,
+ v1.IntegrationConditionKnativeNotInstalledReason,
+ "integration cannot run. Knative is not installed in the cluster",
+ ), fmt.Errorf("integration cannot run. Knative is not installed in the cluster")
+ }
+
+ if t.SinkBinding == nil {
+ allowed := t.isSinkBindingAllowed(e)
+ t.SinkBinding = &allowed
+ }
}
- return true, nil, nil
+ return ptr.Deref(t.Enabled, false), nil, nil
}
func filterMetaItems(meta metadata.IntegrationMetadata, cst knativeapi.CamelServiceType, uriType string) []string {
@@ -158,6 +147,9 @@ func filterMetaItems(meta metadata.IntegrationMetadata, cst knativeapi.CamelServ
uris = meta.ToURIs
}
items = append(items, knativeutil.FilterURIs(uris, cst)...)
+ if len(items) == 0 {
+ return nil
+ }
sort.Strings(items)
return items
}
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index 3d55db707a..0a53459923 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -61,9 +61,6 @@ var _ ControllerStrategySelector = &knativeServiceTrait{}
func newKnativeServiceTrait() Trait {
return &knativeServiceTrait{
BaseTrait: NewBaseTrait(knativeServiceTraitID, knativeServiceTraitOrder),
- KnativeServiceTrait: traitv1.KnativeServiceTrait{
- Annotations: map[string]string{},
- },
}
}
@@ -92,13 +89,7 @@ func (t *knativeServiceTrait) Configure(e *Environment) (bool, *TraitCondition,
if e.Resources.GetDeploymentForIntegration(e.Integration) != nil {
// A controller is already present for the integration
- return false, NewIntegrationCondition(
- "KnativeService",
- v1.IntegrationConditionKnativeServiceAvailable,
- corev1.ConditionFalse,
- v1.IntegrationConditionKnativeServiceNotAvailableReason,
- fmt.Sprintf("different controller strategy used (%s)", string(ControllerStrategyDeployment)),
- ), nil
+ return false, nil, nil
}
strategy, err := e.DetermineControllerStrategy()
@@ -111,22 +102,15 @@ func (t *knativeServiceTrait) Configure(e *Environment) (bool, *TraitCondition,
err.Error(),
), err
}
- if strategy != ControllerStrategyKnativeService {
- return false, NewIntegrationCondition(
- "KnativeService",
- v1.IntegrationConditionKnativeServiceAvailable,
- corev1.ConditionFalse,
- v1.IntegrationConditionKnativeServiceNotAvailableReason,
- fmt.Sprintf("different controller strategy used (%s)", string(strategy)),
- ), nil
- }
- if e.IntegrationInPhase(v1.IntegrationPhaseRunning, v1.IntegrationPhaseError) {
+ if strategy == ControllerStrategyKnativeService {
+ t.Enabled = ptr.To(true)
+ } else if e.IntegrationInPhase(v1.IntegrationPhaseRunning, v1.IntegrationPhaseError) {
condition := e.Integration.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable)
- return condition != nil && condition.Status == corev1.ConditionTrue, nil, nil
+ t.Enabled = ptr.To(condition != nil && condition.Status == corev1.ConditionTrue)
}
- return true, nil, nil
+ return ptr.Deref(t.Enabled, false), nil, nil
}
func (t *knativeServiceTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index 24eae32635..80cf2628cb 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -124,7 +124,7 @@ func TestKnativeService(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -252,7 +252,7 @@ func TestKnativeServiceWithCustomContainerName(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -337,7 +337,7 @@ func TestKnativeServiceWithRest(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -405,7 +405,7 @@ func TestKnativeServiceNotApplicable(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -480,7 +480,7 @@ func TestKnativeServiceNoServingAvailable(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -606,7 +606,7 @@ func createKnativeServiceTestEnvironment(t *testing.T, trait *traitv1.KnativeSer
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(environment)
+ _, _, err = traitCatalog.apply(environment)
require.NoError(t, err)
return environment
@@ -619,7 +619,7 @@ func TestServiceAnnotation(t *testing.T) {
})
traitsCatalog := environment.Catalog
- _, err := traitsCatalog.apply(environment)
+ _, _, err := traitsCatalog.apply(environment)
require.NoError(t, err)
@@ -629,5 +629,77 @@ func TestServiceAnnotation(t *testing.T) {
assert.NotNil(t, service)
assert.True(t, reflect.DeepEqual(service.GetAnnotations(), annotationsTest))
+}
+func TestKnativeServiceAuto(t *testing.T) {
+ catalog, err := camel.DefaultCatalog()
+ require.NoError(t, err)
+
+ client, _ := test.NewFakeClient()
+ traitCatalog := NewCatalog(nil)
+
+ compressedRoute, err := gzip.CompressBase64([]byte(`from("platform-http:test").log("hello")`))
+ require.NoError(t, err)
+
+ environment := Environment{
+ CamelCatalog: catalog,
+ Catalog: traitCatalog,
+ Client: client,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: KnativeServiceTestName,
+ Namespace: KnativeServiceTestNamespace,
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseDeploying,
+ },
+ Spec: v1.IntegrationSpec{
+ Profile: v1.TraitProfileKnative,
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "routes.js",
+ Content: string(compressedRoute),
+ Compression: true,
+ },
+ Language: v1.LanguageJavaScript,
+ },
+ },
+ },
+ },
+ IntegrationKit: &v1.IntegrationKit{
+ Status: v1.IntegrationKitStatus{
+ Phase: v1.IntegrationKitPhaseReady,
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ Spec: v1.IntegrationPlatformSpec{
+ Cluster: v1.IntegrationPlatformClusterOpenShift,
+ Build: v1.IntegrationPlatformBuildSpec{
+ PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+ 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(),
+ }
+ environment.Platform.ResyncStatusFullConfig()
+
+ // don't care about conditions in this unit test
+ _, traits, err := traitCatalog.apply(&environment)
+
+ require.NoError(t, err)
+ assert.NotEmpty(t, traits)
+ assert.NotEmpty(t, environment.ExecutedTraits)
+ assert.Equal(t, &traitv1.KnativeServiceTrait{
+ Trait: traitv1.Trait{
+ Enabled: ptr.To(true),
+ },
+ }, traits.KnativeService)
}
diff --git a/pkg/trait/knative_test.go b/pkg/trait/knative_test.go
index 7a8a7e45f0..7a6ebe49f0 100644
--- a/pkg/trait/knative_test.go
+++ b/pkg/trait/knative_test.go
@@ -355,7 +355,7 @@ func TestKnativeTriggerExplicitFilterConfig(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -455,7 +455,7 @@ func TestKnativeTriggerExplicitFilterConfigNoEventTypeFilter(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -552,7 +552,7 @@ func TestKnativeTriggerDefaultEventTypeFilter(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -649,7 +649,7 @@ func TestKnativeTriggerDefaultEventTypeFilterDisabled(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -749,7 +749,7 @@ func TestKnativeMultipleTrigger(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -887,7 +887,7 @@ func TestKnativeMultipleTriggerAdditionalFilterConfig(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -1022,7 +1022,7 @@ func TestKnativeTriggerNoEventType(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -1119,7 +1119,7 @@ func TestKnativeTriggerNoServingAvailable(t *testing.T) {
environment.Platform.ResyncStatusFullConfig()
// don't care about conditions in this unit test
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -1180,7 +1180,7 @@ func TestKnativePlatformHttpConfig(t *testing.T) {
err = tc.Configure(&environment)
require.NoError(t, err)
- _, err = tc.apply(&environment)
+ _, _, err = tc.apply(&environment)
require.NoError(t, err)
assert.Contains(t, environment.Integration.Status.Capabilities, v1.CapabilityPlatformHTTP)
})
@@ -1226,8 +1226,9 @@ func TestKnativePlatformHttpDependencies(t *testing.T) {
err = tc.Configure(&environment)
require.NoError(t, err)
- conditions, err := tc.apply(&environment)
+ conditions, traits, err := tc.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.Contains(t, environment.Integration.Status.Capabilities, v1.CapabilityPlatformHTTP)
assert.Contains(t, environment.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus:camel-quarkus-platform-http")
@@ -1653,7 +1654,7 @@ func TestKnativeSinkBinding(t *testing.T) {
err = tc.Configure(&environment)
require.NoError(t, err)
- _, err = tc.apply(&environment)
+ _, _, err = tc.apply(&environment)
require.NoError(t, err)
baseProp := "camel.component.knative.environment.resources[0]"
assert.Equal(t, "channel-sink-1", environment.ApplicationProperties[baseProp+".name"])
@@ -1806,3 +1807,63 @@ func createEnvironmentMissingEventingCRDs() *Environment {
return environment
}
+
+func TestKnativeAutoConfiguration(t *testing.T) {
+ client, _ := test.NewFakeClient()
+ replicas := int32(3)
+ catalog, _ := camel.QuarkusCatalog()
+ environment := &Environment{
+ CamelCatalog: catalog,
+ Catalog: NewCatalog(nil),
+ Client: client,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "integration-name",
+ },
+ Spec: v1.IntegrationSpec{
+ Replicas: &replicas,
+ Traits: v1.Traits{},
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseInitialization,
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "namespace",
+ },
+ Spec: v1.IntegrationPlatformSpec{
+ Cluster: v1.IntegrationPlatformClusterKubernetes,
+ Profile: v1.TraitProfileKubernetes,
+ },
+ },
+ Resources: kubernetes.NewCollection(),
+ ApplicationProperties: make(map[string]string),
+ }
+ environment.Platform.ResyncStatusFullConfig()
+
+ trait, _ := newKnativeTrait().(*knativeTrait)
+ environment.Integration.Spec.Sources = []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "test.java",
+ Content: `
+ from("knative:channel/test").to("log:${body};
+ `,
+ },
+ Language: v1.LanguageJavaSource,
+ },
+ }
+
+ configured, condition, err := trait.Configure(environment)
+ require.NoError(t, err)
+ assert.Nil(t, condition)
+ assert.True(t, configured)
+ err = trait.Apply(environment)
+ require.NoError(t, err)
+ expectedTrait, _ := newKnativeTrait().(*knativeTrait)
+ expectedTrait.Enabled = ptr.To(true)
+ expectedTrait.SinkBinding = ptr.To(false)
+ expectedTrait.ChannelSources = []string{"knative:channel/test"}
+ assert.Equal(t, expectedTrait, trait)
+}
diff --git a/pkg/trait/logging.go b/pkg/trait/logging.go
index fdd6656a47..8d88d21fcc 100644
--- a/pkg/trait/logging.go
+++ b/pkg/trait/logging.go
@@ -44,13 +44,10 @@ type loggingTrait struct {
func newLoggingTraitTrait() Trait {
return &loggingTrait{
BaseTrait: NewBaseTrait(loggingTraitID, loggingTraitOrder),
- LoggingTrait: traitv1.LoggingTrait{
- Level: defaultLogLevel,
- },
}
}
-func (l loggingTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
+func (l *loggingTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
if e.Integration == nil {
return false, nil, nil
}
@@ -61,7 +58,7 @@ func (l loggingTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
return e.IntegrationInRunningPhases(), nil, nil
}
-func (l loggingTrait) Apply(e *Environment) error {
+func (l *loggingTrait) Apply(e *Environment) error {
if e.CamelCatalog.Runtime.Capabilities["logging"].RuntimeProperties != nil {
l.setCatalogConfiguration(e)
} else {
@@ -72,8 +69,8 @@ func (l loggingTrait) Apply(e *Environment) error {
}
// Deprecated: to be removed in future release in favor of func setCatalogConfiguration().
-func (l loggingTrait) setEnvConfiguration(e *Environment) {
- envvar.SetVal(&e.EnvVars, envVarQuarkusLogLevel, l.Level)
+func (l *loggingTrait) setEnvConfiguration(e *Environment) {
+ envvar.SetVal(&e.EnvVars, envVarQuarkusLogLevel, l.getLevel())
if l.Format != "" {
envvar.SetVal(&e.EnvVars, envVarQuarkusLogConsoleFormat, l.Format)
@@ -94,11 +91,11 @@ func (l loggingTrait) setEnvConfiguration(e *Environment) {
}
}
-func (l loggingTrait) setCatalogConfiguration(e *Environment) {
+func (l *loggingTrait) setCatalogConfiguration(e *Environment) {
if e.ApplicationProperties == nil {
e.ApplicationProperties = make(map[string]string)
}
- e.ApplicationProperties["camel.k.logging.level"] = l.Level
+ e.ApplicationProperties["camel.k.logging.level"] = l.getLevel()
if l.Format != "" {
e.ApplicationProperties["camel.k.logging.format"] = l.Format
}
@@ -121,3 +118,11 @@ func (l loggingTrait) setCatalogConfiguration(e *Environment) {
}
}
}
+
+func (l *loggingTrait) getLevel() string {
+ if l.Level == "" {
+ return defaultLogLevel
+ }
+
+ return l.Level
+}
diff --git a/pkg/trait/logging_test.go b/pkg/trait/logging_test.go
index 7d77ff7e07..49a4ec878d 100644
--- a/pkg/trait/logging_test.go
+++ b/pkg/trait/logging_test.go
@@ -113,9 +113,10 @@ func NewLoggingTestCatalog() *Catalog {
func TestEmptyLoggingTrait(t *testing.T) {
env := createDefaultLoggingTestEnv(t)
- conditions, err := NewLoggingTestCatalog().apply(env)
+ conditions, traits, err := NewLoggingTestCatalog().apply(env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
@@ -135,9 +136,10 @@ func TestEmptyLoggingTrait(t *testing.T) {
func TestJsonLoggingTrait(t *testing.T) {
// When running, this log should look like "09:07:00 INFO (main) Profile prod activated."
env := createLoggingTestEnv(t, true, true, true, "TRACE", "%d{HH:mm:ss} %-5p (%t) %s%e%n")
- conditions, err := NewLoggingTestCatalog().apply(env)
+ conditions, traits, err := NewLoggingTestCatalog().apply(env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
@@ -162,9 +164,10 @@ func TestDefaultQuarkusLogging(t *testing.T) {
RuntimeProperties: nil,
}
env.EnvVars = []corev1.EnvVar{}
- conditions, err := NewLoggingTestCatalog().apply(env)
+ conditions, traits, err := NewLoggingTestCatalog().apply(env)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, env.ExecutedTraits)
diff --git a/pkg/trait/mount_test.go b/pkg/trait/mount_test.go
index f23e1bbbc9..0a480e3147 100644
--- a/pkg/trait/mount_test.go
+++ b/pkg/trait/mount_test.go
@@ -43,9 +43,10 @@ func TestMountVolumesEmpty(t *testing.T) {
environment.Integration.Spec.Traits = v1.Traits{} // empty traits
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("mount"))
@@ -66,9 +67,10 @@ func TestMountVolumesIntegrationPhaseDeploying(t *testing.T) {
environment := getNominalEnv(t, traitCatalog)
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("mount"))
@@ -116,9 +118,10 @@ func TestEmptyDirVolumeIntegrationPhaseDeploying(t *testing.T) {
EmptyDirs: []string{"my-empty-dir:/some/path"},
}
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("mount"))
@@ -161,9 +164,10 @@ func TestMountVolumesIntegrationPhaseInitialization(t *testing.T) {
environment.Integration.Status.Phase = v1.IntegrationPhaseInitialization
environment.Platform.ResyncStatusFullConfig()
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("mount"))
diff --git a/pkg/trait/platform.go b/pkg/trait/platform.go
index cc9a04bbbb..d129e4bca6 100644
--- a/pkg/trait/platform.go
+++ b/pkg/trait/platform.go
@@ -39,6 +39,9 @@ const (
type platformTrait struct {
BasePlatformTrait
traitv1.PlatformTrait `property:",squash"`
+ // Parameters to be used internally
+ createDefault *bool
+ global *bool
}
func newPlatformTrait() Trait {
@@ -62,17 +65,17 @@ func (t *platformTrait) Configure(e *Environment) (bool, *TraitCondition, error)
if ocp, err := openshift.IsOpenShift(t.Client); err != nil {
return false, nil, err
} else if ocp {
- t.CreateDefault = ptr.To(true)
+ t.createDefault = ptr.To(true)
} else if addr, err := image.GetRegistryAddress(e.Ctx, t.Client); err != nil {
return false, nil, err
} else if addr != nil {
- t.CreateDefault = ptr.To(true)
+ t.createDefault = ptr.To(true)
}
}
if t.Global == nil {
globalOperator := platform.IsCurrentOperatorGlobal()
- t.Global = &globalOperator
+ t.global = &globalOperator
}
return true, nil, nil
@@ -117,7 +120,7 @@ func (t *platformTrait) getOrCreatePlatform(e *Environment) (*v1.IntegrationPlat
if err != nil && !apierrors.IsNotFound(err) {
return nil, err
}
- if apierrors.IsNotFound(err) && ptr.Deref(t.CreateDefault, false) {
+ if apierrors.IsNotFound(err) && ptr.Deref(t.getCreateDefault(), false) {
pl = t.createDefaultPlatform(e)
e.Resources.Add(pl)
@@ -146,7 +149,7 @@ func (t *platformTrait) createDefaultPlatform(e *Environment) *v1.IntegrationPla
platformName = platform.DefaultPlatformName
}
namespace := e.Integration.Namespace
- if ptr.Deref(t.Global, false) {
+ if ptr.Deref(t.getGlobal(), false) {
operatorNamespace := platform.GetOperatorNamespace()
if operatorNamespace != "" {
namespace = operatorNamespace
@@ -175,3 +178,19 @@ func (t *platformTrait) installViewerRole(e *Environment, itp *v1.IntegrationPla
t.L.Infof("Cannot install global IntegrationPlatform viewer role in namespace '%s': skipping.", itp.Namespace)
}
}
+
+func (t *platformTrait) getCreateDefault() *bool {
+ if t.CreateDefault == nil {
+ return t.createDefault
+ }
+
+ return t.CreateDefault
+}
+
+func (t *platformTrait) getGlobal() *bool {
+ if t.Global == nil {
+ return t.global
+ }
+
+ return t.Global
+}
diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go
index 4138ff8fd5..ba11aaa55a 100644
--- a/pkg/trait/prometheus.go
+++ b/pkg/trait/prometheus.go
@@ -44,9 +44,6 @@ type prometheusTrait struct {
func newPrometheusTrait() Trait {
return &prometheusTrait{
BaseTrait: NewBaseTrait(prometheusTraitID, prometheusTraitOrder),
- PrometheusTrait: traitv1.PrometheusTrait{
- PodMonitor: ptr.To(true),
- },
}
}
@@ -89,7 +86,7 @@ func (t *prometheusTrait) Apply(e *Environment) error {
condition.Message = fmt.Sprintf("%s(%d)", container.Name, containerPort.ContainerPort)
// Add the PodMonitor resource
- if ptr.Deref(t.PodMonitor, false) {
+ if ptr.Deref(t.PodMonitor, true) {
portName := containerPort.Name
podMonitor, err := t.getPodMonitorFor(e, portName)
if err != nil {
diff --git a/pkg/trait/route.go b/pkg/trait/route.go
index c35b83c879..710bb3a368 100644
--- a/pkg/trait/route.go
+++ b/pkg/trait/route.go
@@ -48,9 +48,6 @@ type routeTrait struct {
func newRouteTrait() Trait {
return &routeTrait{
BaseTrait: NewBaseTrait(routeTraitID, routeTraitOrder),
- RouteTrait: traitv1.RouteTrait{
- Annotations: map[string]string{},
- },
}
}
diff --git a/pkg/trait/route_test.go b/pkg/trait/route_test.go
index 376464fa68..2ab1b31065 100644
--- a/pkg/trait/route_test.go
+++ b/pkg/trait/route_test.go
@@ -207,8 +207,9 @@ func TestRoute_Default(t *testing.T) {
environment := createTestRouteEnvironment(t, name)
traitsCatalog := environment.Catalog
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("container"))
@@ -243,8 +244,9 @@ func TestRoute_Disabled(t *testing.T) {
"explicitly disabled",
)
traitsCatalog := environment.Catalog
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, expectedCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("route"))
@@ -282,9 +284,10 @@ func TestRoute_Host(t *testing.T) {
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("route"))
@@ -313,9 +316,10 @@ func TestRoute_TLS_From_Secret_reencrypt(t *testing.T) {
TLSDestinationCACertificateSecret: tlsMultipleSecretsName + "/" + tlsMultipleSecretsCert3Key,
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("route"))
@@ -349,7 +353,8 @@ func TestRoute_TLS_wrong_secret(t *testing.T) {
TLSDestinationCACertificateSecret: "404",
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
+ assert.Empty(t, traits)
assert.Empty(t, conditions)
// there must be errors as the trait has wrong configuration
require.Error(t, err)
@@ -377,7 +382,8 @@ func TestRoute_TLS_secret_wrong_key(t *testing.T) {
TLSCACertificateSecret: tlsMultipleSecretsName + "/foo",
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
+ assert.Empty(t, traits)
assert.Empty(t, conditions)
// there must be errors as the trait has wrong configuration
require.Error(t, err)
@@ -405,7 +411,8 @@ func TestRoute_TLS_secret_missing_key(t *testing.T) {
TLSCACertificateSecret: tlsMultipleSecretsName,
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
+ assert.Empty(t, traits)
assert.Empty(t, conditions)
// there must be errors as the trait has wrong configuration
require.Error(t, err)
@@ -434,8 +441,9 @@ func TestRoute_TLS_reencrypt(t *testing.T) {
TLSDestinationCACertificate: destinationCaCert,
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("route"))
@@ -468,8 +476,9 @@ func TestRoute_TLS_edge(t *testing.T) {
TLSCACertificate: caCert,
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("route"))
@@ -500,8 +509,9 @@ func TestRoute_TLS_passthrough(t *testing.T) {
TLSInsecureEdgeTerminationPolicy: string(routev1.InsecureEdgeTerminationPolicyAllow),
},
}
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("route"))
@@ -530,8 +540,9 @@ func TestRoute_WithCustomServicePort(t *testing.T) {
}
traitsCatalog := environment.Catalog
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("container"))
@@ -564,8 +575,9 @@ func TestRouteAnnotation(t *testing.T) {
}
traitsCatalog := environment.Catalog
- conditions, err := traitsCatalog.apply(environment)
+ conditions, traits, err := traitsCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
route := environment.Resources.GetRoute(func(r *routev1.Route) bool {
diff --git a/pkg/trait/security_context.go b/pkg/trait/security_context.go
index c43d90f980..d02c58a3f0 100644
--- a/pkg/trait/security_context.go
+++ b/pkg/trait/security_context.go
@@ -44,10 +44,6 @@ type securityContextTrait struct {
func newSecurityContextTrait() Trait {
return &securityContextTrait{
BasePlatformTrait: NewBasePlatformTrait(securityContextTraitID, securityContextTraitOder),
- SecurityContextTrait: traitv1.SecurityContextTrait{
- RunAsNonRoot: ptr.To(defaultPodRunAsNonRoot),
- SeccompProfileType: defaultPodSeccompProfileType,
- },
}
}
@@ -66,7 +62,9 @@ func (t *securityContextTrait) Configure(e *Environment) (bool, *TraitCondition,
if condition != nil && condition.Status == corev1.ConditionTrue {
return false, NewIntegrationConditionPlatformDisabledWithMessage(
"SecurityContext",
- "pod security context is disabled for Knative Service. PodSecurityContext properties can affect non-user sidecar containers that come from Knative or your service mesh. Use container security context instead.",
+ "pod security context is disabled for Knative Service. "+
+ "PodSecurityContext properties can affect non-user sidecar containers that come from Knative or your service mesh. "+
+ "Use container security context instead.",
), nil
}
@@ -83,9 +81,9 @@ func (t *securityContextTrait) Apply(e *Environment) error {
func (t *securityContextTrait) setSecurityContext(e *Environment, podSpec *corev1.PodSpec) error {
sc := corev1.PodSecurityContext{
- RunAsNonRoot: t.RunAsNonRoot,
+ RunAsNonRoot: t.getRunAsNonRoot(),
SeccompProfile: &corev1.SeccompProfile{
- Type: t.SeccompProfileType,
+ Type: t.getSeccompProfileType(),
},
}
@@ -123,3 +121,19 @@ func (t *securityContextTrait) getUser(e *Environment) (*int64, error) {
return runAsUser, nil
}
+
+func (t *securityContextTrait) getRunAsNonRoot() *bool {
+ if t.RunAsNonRoot == nil {
+ return ptr.To(defaultPodRunAsNonRoot)
+ }
+
+ return t.RunAsNonRoot
+}
+
+func (t *securityContextTrait) getSeccompProfileType() corev1.SeccompProfileType {
+ if t.SeccompProfileType == "" {
+ return defaultPodSeccompProfileType
+ }
+
+ return t.SeccompProfileType
+}
diff --git a/pkg/trait/security_context_test.go b/pkg/trait/security_context_test.go
index 9315657fa0..b9a49a2436 100644
--- a/pkg/trait/security_context_test.go
+++ b/pkg/trait/security_context_test.go
@@ -40,9 +40,10 @@ func TestDefaultPodKubernetesSecurityContextInitializationPhase(t *testing.T) {
environment.Integration.Status.Phase = v1.IntegrationPhaseInitialization
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("security-context"))
@@ -52,9 +53,10 @@ func TestDefaultPodKubernetesSecurityContext(t *testing.T) {
environment := createPodSettingContextEnvironment(t, v1.TraitProfileKubernetes)
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.Empty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -72,9 +74,10 @@ func TestDefaultPodOpenshiftSecurityContext(t *testing.T) {
environment := createOpenshiftPodSettingContextEnvironment(t, v1.TraitProfileOpenShift)
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployment"))
@@ -97,9 +100,10 @@ func TestDefaultPodKnativeSecurityContext(t *testing.T) {
}
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.NotEmpty(t, conditions)
assert.NotEmpty(t, environment.ExecutedTraits)
assert.Nil(t, environment.GetTrait("deployment"))
@@ -125,9 +129,10 @@ func TestUserPodSecurityContext(t *testing.T) {
}
traitCatalog := NewCatalog(nil)
- conditions, err := traitCatalog.apply(environment)
+ conditions, traits, err := traitCatalog.apply(environment)
require.NoError(t, err)
+ assert.NotEmpty(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 087f289dba..b114115f63 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -86,7 +86,8 @@ func (t *serviceTrait) Configure(e *Environment) (bool, *TraitCondition, error)
)
return false, condition, err
}
- return exposeHTTPServices, nil, nil
+
+ t.Enabled = ptr.To(exposeHTTPServices)
}
return ptr.Deref(t.Enabled, false), nil, nil
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index b61149115f..4d0f3f0859 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -109,7 +109,7 @@ func TestServiceWithDefaults(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -216,7 +216,7 @@ func TestService(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -303,7 +303,7 @@ func TestServiceWithCustomContainerName(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -394,7 +394,7 @@ func TestServiceWithNodePort(t *testing.T) {
}
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(&environment)
+ _, _, err = traitCatalog.apply(&environment)
require.NoError(t, err)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -503,9 +503,10 @@ func TestServiceWithKnativeServiceEnabled(t *testing.T) {
"TraitConfiguration",
"explicitly disabled by the platform: knative-service trait has priority over this trait",
)
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, deploymentCondition)
assert.Contains(t, conditions, serviceCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -583,9 +584,10 @@ func TestServicesWithKnativeProfile(t *testing.T) {
"TraitConfiguration",
"explicitly disabled by the platform: knative-service trait has priority over this trait",
)
- conditions, err := traitCatalog.apply(&environment)
+ conditions, traits, err := traitCatalog.apply(&environment)
require.NoError(t, err)
+ assert.NotEmpty(t, traits)
assert.Contains(t, conditions, deploymentCondition)
assert.Contains(t, conditions, serviceCondition)
assert.NotEmpty(t, environment.ExecutedTraits)
@@ -664,11 +666,77 @@ func TestServiceWithKnativeServiceDisabledInIntegrationPlatform(t *testing.T) {
"KnativeServiceNotAvailable",
"explicitly disabled",
)
- conditions, err := traitCatalog.apply(&environment)
+ 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))
}
+
+func TestServiceAutoConfiguration(t *testing.T) {
+ catalog, err := camel.DefaultCatalog()
+ require.NoError(t, err)
+
+ client, _ := test.NewFakeClient()
+ traitCatalog := NewCatalog(nil)
+
+ compressedRoute, err := gzip.CompressBase64([]byte(`from("netty-http:test").log("hello")`))
+ require.NoError(t, err)
+
+ environment := Environment{
+ CamelCatalog: catalog,
+ Catalog: traitCatalog,
+ Client: client,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: ServiceTestName,
+ Namespace: "ns",
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseDeploying,
+ },
+ Spec: v1.IntegrationSpec{
+ Profile: v1.TraitProfileKubernetes,
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "routes.js",
+ Content: string(compressedRoute),
+ Compression: true,
+ },
+ Language: v1.LanguageJavaScript,
+ },
+ },
+ },
+ },
+ IntegrationKit: &v1.IntegrationKit{
+ Status: v1.IntegrationKitStatus{
+ Phase: v1.IntegrationKitPhaseReady,
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ Spec: v1.IntegrationPlatformSpec{
+ Cluster: v1.IntegrationPlatformClusterOpenShift,
+ Build: v1.IntegrationPlatformBuildSpec{
+ PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+ 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(),
+ }
+ environment.Platform.ResyncStatusFullConfig()
+
+ _, traits, err := traitCatalog.apply(&environment)
+ require.NoError(t, err)
+ assert.Equal(t, ptr.To(true), traits.Service.Enabled)
+}
diff --git a/pkg/trait/trait.go b/pkg/trait/trait.go
index 5d9076c135..93c10a74aa 100644
--- a/pkg/trait/trait.go
+++ b/pkg/trait/trait.go
@@ -57,22 +57,28 @@ func Apply(ctx context.Context, c client.Client, integration *v1.Integration, ki
environment.Catalog = catalog
// invoke the trait framework to determine the needed resources
- conditions, err := catalog.apply(environment)
- // Conditions contains informative message coming from the trait execution and useful to be reported into it or ik CR
+ conditions, traits, err := catalog.apply(environment)
+ // WARNING: Conditions contains informative message coming from the trait execution and useful to be reported into it or ik CR
// they must be applied before returning after an error
for _, tc := range conditions {
switch {
case integration != nil:
- // set an Integration condition
integration.Status.SetCondition(tc.integrationCondition())
case kit != nil:
- // set an IntegrationKit condition
kit.Status.SetCondition(tc.integrationKitCondition())
}
}
if err != nil {
return nil, fmt.Errorf("error during trait customization: %w", err)
}
+ // Set the executed traits taking care to merge in order to avoid the distinct execution
+ // phase to clean up any previous executed trait
+ if integration != nil {
+ integration.Status.Traits = integration.Spec.Traits.DeepCopy()
+ if err := integration.Status.Traits.Merge(*traits); err != nil {
+ return nil, fmt.Errorf("error setting status traits: %w", err)
+ }
+ }
postActionErrors := make([]error, 0)
// execute post actions registered by traits
@@ -172,7 +178,7 @@ func NewSyntheticEnvironment(ctx context.Context, c client.Client, integration *
// set the catalog
env.Catalog = catalog
// we need to simulate the execution of the traits to fill certain values used later by monitoring
- _, err := catalog.apply(&env)
+ _, _, err := catalog.apply(&env)
if err != nil {
return nil, fmt.Errorf("error during trait customization: %w", err)
}
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index 867c758143..bdf62d009b 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -27,6 +27,7 @@ import (
"github.com/apache/camel-k/v2/pkg/client"
"github.com/apache/camel-k/v2/pkg/util/log"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/util/json"
)
// Catalog collects all information about traits in one place.
@@ -86,10 +87,10 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait {
return res
}
-func (c *Catalog) apply(environment *Environment) ([]*TraitCondition, error) {
+func (c *Catalog) apply(environment *Environment) ([]*TraitCondition, *v1.Traits, error) {
traitsConditions := []*TraitCondition{}
if err := c.Configure(environment); err != nil {
- return traitsConditions, err
+ return traitsConditions, nil, err
}
traits := c.traitsFor(environment)
environment.ConfiguredTraits = traits
@@ -107,49 +108,89 @@ func (c *Catalog) apply(environment *Environment) ([]*TraitCondition, error) {
traitsConditions = append(traitsConditions, condition)
}
if err != nil {
- return traitsConditions, fmt.Errorf("%s trait configuration failed: %w", trait.ID(), err)
+ return traitsConditions, nil, fmt.Errorf("%s trait configuration failed: %w", trait.ID(), err)
}
-
if enabled {
err = trait.Apply(environment)
if err != nil {
- return traitsConditions, fmt.Errorf("%s trait execution failed: %w", trait.ID(), err)
+ return traitsConditions, nil, fmt.Errorf("%s trait execution failed: %w", trait.ID(), err)
}
environment.ExecutedTraits = append(environment.ExecutedTraits, trait)
// execute post step processors
for _, processor := range environment.PostStepProcessors {
err := processor(environment)
if err != nil {
- return traitsConditions, fmt.Errorf("%s trait executing post step action failed: %w", trait.ID(), err)
+ return traitsConditions, nil, fmt.Errorf("%s trait executing post step action failed: %w", trait.ID(), err)
}
}
}
}
- traitsConditions = append(traitsConditions, c.executedTraitCondition(environment.ExecutedTraits))
+ cs, ts, err := c.executedTraitCondition(environment.ExecutedTraits)
+ if err != nil {
+ return traitsConditions, &ts, err
+ }
+ traitsConditions = append(traitsConditions, cs)
if !applicable && environment.PlatformInPhase(v1.IntegrationPlatformPhaseReady) {
- return traitsConditions, errors.New("no trait can be executed because of no ready platform found")
+ return traitsConditions, nil, errors.New("no trait can be executed because of no ready platform found")
}
for _, processor := range environment.PostProcessors {
err := processor(environment)
if err != nil {
- return traitsConditions, fmt.Errorf("error executing post processor: %w", err)
+ return traitsConditions, nil, fmt.Errorf("error executing post processor: %w", err)
}
}
- return traitsConditions, nil
+ return traitsConditions, &ts, nil
}
-func (c *Catalog) executedTraitCondition(executedTrait []Trait) *TraitCondition {
+func (c *Catalog) executedTraitCondition(executedTrait []Trait) (*TraitCondition, v1.Traits, error) {
+ var traits v1.Traits
+ var traitMap = make(map[string]map[string]interface{})
traitIds := make([]string, 0)
for _, trait := range executedTrait {
+ data, err := json.Marshal(trait)
+ if err != nil {
+ return nil, traits, err
+ }
+ var traitIDMap map[string]interface{}
+ if err := json.Unmarshal(data, &traitIDMap); err != nil {
+ return nil, traits, err
+ }
+ if len(traitIDMap) > 0 {
+ if isAddon(string(trait.ID())) {
+ traitMap["addons"] = map[string]interface{}{
+ string(trait.ID()): traitIDMap,
+ }
+ } else {
+ traitMap[string(trait.ID())] = traitIDMap
+ }
+ }
+
traitIds = append(traitIds, string(trait.ID()))
}
+
+ traitData, err := json.Marshal(traitMap)
+ if err != nil {
+ return nil, traits, err
+ }
+ if err := json.Unmarshal(traitData, &traits); err != nil {
+ return nil, traits, err
+ }
+
message := fmt.Sprintf("Applied traits: %s", strings.Join(traitIds, ","))
c.L.Debugf(message)
- return NewIntegrationCondition("", v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message)
+ return NewIntegrationCondition("", v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message), traits, nil
+}
+
+// Deprecated: remove this check when we include the addons traits into regular traits
+// see https://github.com/apache/camel-k/issues/5787
+// isAddon returns true if the trait is an addon.
+func isAddon(id string) bool {
+ return id == "master" || id == "keda" || id == "3scale" || id == "tracing" ||
+ id == "aws-secrets-manager" || id == "azure-key-vault" || id == "gcp-secret-manager" || id == "hashicorp-vault"
}
// GetTrait returns the trait with the given ID.
diff --git a/pkg/trait/trait_catalog_test.go b/pkg/trait/trait_catalog_test.go
new file mode 100644
index 0000000000..3475ae2f0e
--- /dev/null
+++ b/pkg/trait/trait_catalog_test.go
@@ -0,0 +1,89 @@
+/*
+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 (
+ "context"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+ "github.com/apache/camel-k/v2/pkg/util/camel"
+ "github.com/apache/camel-k/v2/pkg/util/defaults"
+ "github.com/apache/camel-k/v2/pkg/util/kubernetes"
+ "github.com/apache/camel-k/v2/pkg/util/test"
+)
+
+func TestIntegrationExecutedTrait(t *testing.T) {
+ ip := v1.IntegrationPlatform{}
+ ip.Namespace = "ns"
+ ip.Name = "ck"
+ ip.Status = v1.IntegrationPlatformStatus{
+ IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ RuntimeProvider: v1.RuntimeProviderQuarkus,
+ RuntimeVersion: defaults.DefaultRuntimeVersion,
+ },
+ },
+ Phase: v1.IntegrationPlatformPhaseReady,
+ }
+ c, err := test.NewFakeClient(&ip)
+ require.NoError(t, err)
+ catalog := NewCatalog(c)
+ env := Environment{
+ CamelCatalog: &camel.RuntimeCatalog{
+ CamelCatalogSpec: v1.CamelCatalogSpec{
+ Runtime: v1.RuntimeSpec{
+ Version: defaults.DefaultRuntimeVersion,
+ Provider: v1.RuntimeProviderQuarkus,
+ },
+ },
+ },
+ Catalog: catalog,
+ Ctx: context.Background(),
+ Client: c,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "it",
+ Namespace: "ns",
+ },
+ Spec: v1.IntegrationSpec{
+ Profile: v1.TraitProfileKubernetes,
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseRunning,
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type: v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ },
+ Platform: &ip,
+ Resources: kubernetes.NewCollection(),
+ }
+
+ _, ts, err := catalog.apply(&env)
+ require.NoError(t, err)
+ assert.Equal(t, &v1.Traits{}, ts)
+}
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index 1bbf4d06dd..105e4eace7 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -18,10 +18,13 @@ limitations under the License.
package trait
import (
+ "context"
+ "fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "gopkg.in/yaml.v2"
routev1 "github.com/openshift/api/route/v1"
@@ -32,8 +35,10 @@ 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/resources"
"github.com/apache/camel-k/v2/pkg/util/boolean"
"github.com/apache/camel-k/v2/pkg/util/camel"
+ "github.com/apache/camel-k/v2/pkg/util/defaults"
"github.com/apache/camel-k/v2/pkg/util/kubernetes"
"github.com/apache/camel-k/v2/pkg/util/test"
)
@@ -43,7 +48,7 @@ const (
)
func TestOpenShiftTraits(t *testing.T) {
- env := createTestEnv(t, v1.IntegrationPlatformClusterOpenShift, "camel:core")
+ env := createTestEnv(t, v1.IntegrationPlatformClusterOpenShift, "from('timer:my-timer').to('log:info')")
res := processTestEnv(t, env)
assert.NotEmpty(t, env.ExecutedTraits)
@@ -413,7 +418,7 @@ func processTestEnv(t *testing.T, env *Environment) *kubernetes.Collection {
t.Helper()
catalog := NewTraitTestCatalog()
- _, err := catalog.apply(env)
+ _, _, err := catalog.apply(env)
require.NoError(t, err)
return env.Resources
}
@@ -478,11 +483,11 @@ func NewTraitTestCatalog() *Catalog {
}
func TestExecutedTraitsCondition(t *testing.T) {
- env := createTestEnv(t, v1.IntegrationPlatformClusterOpenShift, "camel:core")
+ env := createTestEnv(t, v1.IntegrationPlatformClusterOpenShift, "from('timer:test').to('log:info')")
catalog := NewTraitTestCatalog()
- conditions, err := catalog.apply(env)
+ conditions, traits, err := catalog.apply(env)
require.NoError(t, err)
-
+ assert.Empty(t, traits)
expectedCondition := NewIntegrationCondition(
"",
v1.IntegrationConditionTraitInfo,
@@ -492,3 +497,192 @@ func TestExecutedTraitsCondition(t *testing.T) {
)
assert.Contains(t, conditions, expectedCondition)
}
+
+func testDefaultIntegrationPhaseTraitsSetting(t *testing.T, phase v1.IntegrationPhase) {
+ it := &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-it",
+ Namespace: "ns",
+ },
+ Spec: v1.IntegrationSpec{
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "file.groovy",
+ Content: "from('timer:test').to('log:info')",
+ },
+ Language: v1.LanguageGroovy,
+ },
+ },
+ },
+ Status: v1.IntegrationStatus{
+ Phase: phase,
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type: v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ }
+ platform := &v1.IntegrationPlatform{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-platform",
+ Namespace: "ns",
+ },
+ Status: v1.IntegrationPlatformStatus{
+ IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ RuntimeProvider: v1.RuntimeProviderQuarkus,
+ RuntimeVersion: defaults.DefaultRuntimeVersion,
+ },
+ },
+ Phase: v1.IntegrationPlatformPhaseReady,
+ },
+ }
+ // Load the default catalog
+ camelCatalogData, err := resources.Resource(fmt.Sprintf("/resources/camel-catalog-%s.yaml", defaults.DefaultRuntimeVersion))
+ require.NoError(t, err)
+ var cat v1.CamelCatalog
+ err = yaml.Unmarshal(camelCatalogData, &cat)
+ require.NoError(t, err)
+ cat.SetAnnotations(platform.Annotations)
+ cat.SetNamespace(platform.Namespace)
+
+ client, err := test.NewFakeClient(platform, &cat)
+ require.NoError(t, err)
+ env, err := Apply(context.Background(), client, it, nil)
+ require.NoError(t, err)
+ assert.NotEmpty(t, env.Integration)
+ // We should get no values slicking from the spec
+ // only traits marked as "auto" should be able to scan
+ // the sources and set values.
+ // Neither default traits values should not be included here.
+ assert.Equal(t, &v1.Traits{}, env.Integration.Status.Traits)
+}
+
+func TestDefaultIntegrationRunningTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseRunning)
+}
+
+func TestDefaultIntegrationNoneTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseNone)
+}
+
+func TestDefaultIntegrationInitTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseInitialization)
+}
+
+func TestDefaultIntegrationWaitingPlatformTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseWaitingForPlatform)
+}
+
+func TestDefaultIntegrationBuildingKitTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseBuildingKit)
+}
+
+func TestDefaultIntegrationDeployingTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseDeploying)
+}
+
+func TestDefaultIntegrationErrorTraitsSetting(t *testing.T) {
+ testDefaultIntegrationPhaseTraitsSetting(t, v1.IntegrationPhaseError)
+}
+
+func TestIntegrationTraitsSetting(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.groovy",
+ Content: "from('timer:test').to('log:info')",
+ },
+ Language: v1.LanguageGroovy,
+ },
+ },
+ Traits: v1.Traits{
+ Builder: &traitv1.BuilderTrait{
+ Properties: []string{
+ "building=yes",
+ },
+ },
+ Camel: &traitv1.CamelTrait{
+ Properties: []string{
+ "hello=world",
+ },
+ },
+ Container: &traitv1.ContainerTrait{
+ Name: "my-container-name",
+ },
+ Addons: map[string]v1.AddonTrait{
+ "master": ToAddonTrait(t, map[string]interface{}{
+ "resourceName": "test-lock",
+ }),
+ },
+ },
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseRunning,
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type: v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ }
+ platform := &v1.IntegrationPlatform{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-platform",
+ Namespace: "ns",
+ },
+ Status: v1.IntegrationPlatformStatus{
+ IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ RuntimeProvider: v1.RuntimeProviderQuarkus,
+ RuntimeVersion: defaults.DefaultRuntimeVersion,
+ },
+ },
+ Phase: v1.IntegrationPlatformPhaseReady,
+ },
+ }
+ // Load the default catalog
+ camelCatalogData, err := resources.Resource(fmt.Sprintf("/resources/camel-catalog-%s.yaml", defaults.DefaultRuntimeVersion))
+ require.NoError(t, err)
+ var cat v1.CamelCatalog
+ err = yaml.Unmarshal(camelCatalogData, &cat)
+ require.NoError(t, err)
+ cat.SetAnnotations(platform.Annotations)
+ cat.SetNamespace(platform.Namespace)
+
+ client, err := test.NewFakeClient(platform, &cat)
+ require.NoError(t, err)
+ env, err := Apply(context.Background(), client, it, nil)
+ require.NoError(t, err)
+ assert.NotEmpty(t, env.Integration)
+ assert.Equal(t, &v1.Traits{
+ Builder: &traitv1.BuilderTrait{
+ Properties: []string{
+ "building=yes",
+ },
+ },
+ Camel: &traitv1.CamelTrait{
+ Properties: []string{
+ "hello=world",
+ },
+ },
+ Container: &traitv1.ContainerTrait{
+ Name: "my-container-name",
+ },
+ Addons: map[string]v1.AddonTrait{
+ "master": ToAddonTrait(t, map[string]interface{}{
+ "resourceName": "test-lock",
+ }),
+ },
+ }, env.Integration.Status.Traits)
+}
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index 7a890af40e..5b6ac50b96 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -670,7 +670,7 @@ func (e *Environment) GetIntegrationContainerName() string {
if dt := e.Catalog.GetTrait(containerTraitID); dt != nil {
if ct, ok := dt.(*containerTrait); ok {
- containerName = ct.Name
+ containerName = ct.getContainerName()
}
}
return containerName
@@ -727,7 +727,7 @@ func (e *Environment) createContainerPort() *corev1.ContainerPort {
if t := e.Catalog.GetTrait(containerTraitID); t != nil {
if ct, ok := t.(*containerTrait); ok {
name = ct.PortName
- port = ct.Port
+ port = ct.getPort()
}
}
@@ -757,7 +757,8 @@ func CapabilityPropertyKey(camelPropertyKey string, vars map[string]string) stri
}
// ConsumeMeta is used to consume metadata information coming from Integration sources. If no sources available,
-// would return false.
+// would return false. When consuming from meta you should make sure that the configuration is stored in the
+// status traits by setting each trait configuration when in "auto" mode.
func (e *Environment) ConsumeMeta(consumeMeta func(metadata.IntegrationMetadata) bool) (bool, error) {
return e.consumeSourcesMeta(nil, consumeMeta)
}
diff --git a/pkg/trait/trait_types_test.go b/pkg/trait/trait_types_test.go
index 8f945397f8..608fc3d076 100644
--- a/pkg/trait/trait_types_test.go
+++ b/pkg/trait/trait_types_test.go
@@ -198,7 +198,7 @@ func TestDetermineControllerStrategySyntheticKitForceKnative(t *testing.T) {
Auto: ptr.To(false),
}
e.Platform.ResyncStatusFullConfig()
- _, err := e.Catalog.apply(e)
+ _, _, err := e.Catalog.apply(e)
require.NoError(t, err)
strategy, err := e.DetermineControllerStrategy()
@@ -270,7 +270,7 @@ func createTestEnvironment(t *testing.T, profile v1.TraitProfile) *Environment {
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(environment)
+ _, _, err = traitCatalog.apply(environment)
require.NoError(t, err)
return environment
@@ -321,7 +321,7 @@ func createNonManagedBuildTestEnvironment(t *testing.T, profile v1.TraitProfile)
environment.Platform.ResyncStatusFullConfig()
- _, err = traitCatalog.apply(environment)
+ _, _, err = traitCatalog.apply(environment)
require.NoError(t, err)
return environment
diff --git a/pkg/trait/util.go b/pkg/trait/util.go
index 6a8083b59c..ec1f62c6fd 100644
--- a/pkg/trait/util.go
+++ b/pkg/trait/util.go
@@ -37,10 +37,6 @@ import (
"github.com/apache/camel-k/v2/pkg/util/sets"
)
-func ptrFrom[T any](value T) *T {
- return &value
-}
-
type Options map[string]map[string]interface{}
func (u Options) Get(id string) (map[string]interface{}, bool) {