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

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


The following commit(s) were added to refs/heads/main by this push:
     new 38df070  feat: Health trait
38df070 is described below

commit 38df070ec3d95992caf9a563a138026c44d79654
Author: Antonin Stefanutti <[email protected]>
AuthorDate: Tue Nov 9 13:16:10 2021 +0100

    feat: Health trait
---
 docs/modules/ROOT/nav.adoc               |   1 +
 docs/modules/traits/pages/container.adoc |  16 ++-
 docs/modules/traits/pages/health.adoc    |  88 +++++++++++++
 e2e/knative/knative_platform_test.go     |   2 +-
 pkg/resources/resources.go               |   6 +-
 pkg/trait/container.go                   | 156 ++++++----------------
 pkg/trait/container_probes_test.go       | 213 ++++++++++++++-----------------
 pkg/trait/container_test.go              |  40 ++++--
 pkg/trait/health.go                      | 195 ++++++++++++++++++++++++++++
 pkg/trait/jolokia.go                     |   2 +-
 pkg/trait/jvm.go                         |   2 +-
 pkg/trait/jvm_test.go                    |   2 +-
 pkg/trait/knative_service.go             |   4 +-
 pkg/trait/prometheus.go                  |   2 +-
 pkg/trait/quarkus.go                     |   2 +-
 pkg/trait/trait_register.go              |   1 +
 pkg/trait/trait_types.go                 |   4 +-
 resources/traits.yaml                    | 116 +++++++++++++----
 18 files changed, 568 insertions(+), 284 deletions(-)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 375ad93..223a98e 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -53,6 +53,7 @@
 ** xref:traits:environment.adoc[Environment]
 ** xref:traits:error-handler.adoc[Error Handler]
 ** xref:traits:gc.adoc[Gc]
+** xref:traits:health.adoc[Health]
 ** xref:traits:ingress.adoc[Ingress]
 ** xref:traits:istio.adoc[Istio]
 ** xref:traits:jolokia.adoc[Jolokia]
diff --git a/docs/modules/traits/pages/container.adoc 
b/docs/modules/traits/pages/container.adoc
index ac5124c..fa48ab3 100755
--- a/docs/modules/traits/pages/container.adoc
+++ b/docs/modules/traits/pages/container.adoc
@@ -5,7 +5,6 @@ The Container trait can be used to configure properties of the 
container where t
 
 It also provides configuration for Services associated to the container.
 
-
 This trait is available in the following profiles: **Kubernetes, Knative, 
OpenShift**.
 
 WARNING: The container trait is a *platform trait*: disabling it may 
compromise the platform functionality.
@@ -83,59 +82,72 @@ The following configuration options are available:
 
 | container.probes-enabled
 | bool
-| ProbesEnabled enable/disable probes on the container (default `false`)
+| DeprecatedProbesEnabled enable/disable probes on the container (default 
`false`)
+Deprecated: replaced by the health trait.
 
 | container.liveness-scheme
 | string
 | Scheme to use when connecting. Defaults to HTTP. Applies to the liveness 
probe.
+Deprecated: replaced by the health trait.
 
 | container.liveness-initial-delay
 | int32
 | Number of seconds after the container has started before liveness probes are 
initiated.
+Deprecated: replaced by the health trait.
 
 | container.liveness-timeout
 | int32
 | Number of seconds after which the probe times out. Applies to the liveness 
probe.
+Deprecated: replaced by the health trait.
 
 | container.liveness-period
 | int32
 | How often to perform the probe. Applies to the liveness probe.
+Deprecated: replaced by the health trait.
 
 | container.liveness-success-threshold
 | int32
 | Minimum consecutive successes for the probe to be considered successful 
after having failed.
 Applies to the liveness probe.
+Deprecated: replaced by the health trait.
 
 | container.liveness-failure-threshold
 | int32
 | Minimum consecutive failures for the probe to be considered failed after 
having succeeded.
 Applies to the liveness probe.
+Deprecated: replaced by the health trait.
 
 | container.readiness-scheme
 | string
 | Scheme to use when connecting. Defaults to HTTP. Applies to the readiness 
probe.
+Deprecated: replaced by the health trait.
 
 | container.readiness-initial-delay
 | int32
 | Number of seconds after the container has started before readiness probes 
are initiated.
+Deprecated: replaced by the health trait.
 
 | container.readiness-timeout
 | int32
 | Number of seconds after which the probe times out. Applies to the readiness 
probe.
+Deprecated: replaced by the health trait.
 
 | container.readiness-period
 | int32
 | How often to perform the probe. Applies to the readiness probe.
+Deprecated: replaced by the health trait.
 
 | container.readiness-success-threshold
 | int32
 | Minimum consecutive successes for the probe to be considered successful 
after having failed.
 Applies to the readiness probe.
+Deprecated: replaced by the health trait.
 
 | container.readiness-failure-threshold
 | int32
 | Minimum consecutive failures for the probe to be considered failed after 
having succeeded.
 Applies to the readiness probe.
+Deprecated: replaced by the health trait.
 
 |===
 
diff --git a/docs/modules/traits/pages/health.adoc 
b/docs/modules/traits/pages/health.adoc
new file mode 100755
index 0000000..6606de9
--- /dev/null
+++ b/docs/modules/traits/pages/health.adoc
@@ -0,0 +1,88 @@
+= Health Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The health trait is responsible for configuring the health probes on the 
integration container.
+
+It's disabled by default.
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, 
OpenShift**.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+[source,console]
+----
+$ kamel run --trait health.[key]=[value] --trait health.[key2]=[value2] 
integration.groovy
+----
+The following configuration options are available:
+
+[cols="2m,1m,5a"]
+|===
+|Property | Type | Description
+
+| health.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common 
property.
+
+| health.liveness-probe-enabled
+| bool
+| Configures the liveness probe for the integration container (default 
`false`).
+
+| health.liveness-scheme
+| string
+| Scheme to use when connecting to the liveness probe (default `HTTP`).
+
+| health.liveness-initial-delay
+| int32
+| Number of seconds after the container has started before the liveness probe 
is initiated.
+
+| health.liveness-timeout
+| int32
+| Number of seconds after which the liveness probe times out.
+
+| health.liveness-period
+| int32
+| How often to perform the liveness probe.
+
+| health.liveness-success-threshold
+| int32
+| Minimum consecutive successes for the liveness probe to be considered 
successful after having failed.
+
+| health.liveness-failure-threshold
+| int32
+| Minimum consecutive failures for the liveness probe to be considered failed 
after having succeeded.
+
+| health.readiness-probe-enabled
+| bool
+| Configures the readiness probe for the integration container (default 
`true`).
+
+| health.readiness-scheme
+| string
+| Scheme to use when connecting to the readiness probe (default `HTTP`).
+
+| health.readiness-initial-delay
+| int32
+| Number of seconds after the container has started before the readiness probe 
is initiated.
+
+| health.readiness-timeout
+| int32
+| Number of seconds after which the readiness probe times out.
+
+| health.readiness-period
+| int32
+| How often to perform the readiness probe.
+
+| health.readiness-success-threshold
+| int32
+| Minimum consecutive successes for the readiness probe to be considered 
successful after having failed.
+
+| health.readiness-failure-threshold
+| int32
+| Minimum consecutive failures for the readiness probe to be considered failed 
after having succeeded.
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/e2e/knative/knative_platform_test.go 
b/e2e/knative/knative_platform_test.go
index 8a6f280..f75a690 100644
--- a/e2e/knative/knative_platform_test.go
+++ b/e2e/knative/knative_platform_test.go
@@ -71,7 +71,7 @@ func TestKnativePlatform(t *testing.T) {
                        Eventually(IntegrationPhase(ns, 
"yaml")).Should(Equal(v1.IntegrationPhaseRunning))
                        Eventually(IntegrationLogs(ns, "yaml"), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!!!"))
                        // It should keep the old profile saved in status
-                       Eventually(IntegrationProfile(ns, "yaml"), 
TestTimeoutMedium).Should(Equal(v1.TraitProfile(string(cluster))))
+                       Eventually(IntegrationProfile(ns, "yaml"), 
TestTimeoutMedium).Should(Equal(v1.TraitProfile(cluster)))
 
                        Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).To(Succeed())
                })
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 55dfc34..b8af443 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -534,14 +534,14 @@ var assets = func() http.FileSystem {
                        modTime:          time.Time{},
                        uncompressedSize: 89871,
 
-                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x4b\x77\xdb\x38\xb6\xee\xdc\xbf\x82\xab\x32\x39\x67\xdd\x16\xba\x2a\xd5\xf7\xd4\x5d\x75\x47\xb6\x1c\x27\x76\x6c\xc7\x89\xdc\x49\xba\x27\xb5\x20\x12\x92\x60\x91\x04\x0d\x80\xb2\x9c\x5f\x7f\x16\x40\xf0\x29\x65\xf3\xe1\x0d\xb7\x06\xe2\x03\x1b\xdf\xc6\xfe\xf0\x20\xde\x78\x13\xcc\xf0\x7e\x27\x6f\x82\x6b\x1e\xb2\x54\xb1\x28\xd0\x22\xd0\x1b\x16\x9c\x66\x34\xdc\xb0\x60\x21\x56\xfa\x89\x4a\x16\x5c\x88\x3c\x8d\xa8\xe6\x
 [...]
+                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x7d\x4b\x77\xdb\x38\xb6\xee\xdc\xbf\x82\xab\x32\x39\x67\xdd\x16\xba\x2a\xd5\xf7\xd4\x5d\x75\x47\xb6\x1c\x27\x76\x6c\xc7\x89\xdc\x49\xba\x27\xb5\x20\x12\x92\x60\x91\x04\x0d\x80\xb2\x9c\x5f\x7f\x16\x40\xf0\x29\x65\xf3\xe1\x0d\xb7\x06\xe2\x03\x1b\xdf\xc6\xfe\xf0\x20\xde\x78\x13\xcc\xf0\x7e\x27\x6f\x82\x6b\x1e\xb2\x54\xb1\x28\xd0\x22\xd0\x1b\x16\x9c\x66\x34\xdc\xb0\x60\x21\x56\xfa\x89\x4a\x16\x5c\x88\x3c\x8d\xa8\xe6\x
 [...]
                },
                "/traits.yaml": &vfsgen۰CompressedFileInfo{
                        name:             "traits.yaml",
                        modTime:          time.Time{},
-                       uncompressedSize: 43798,
+                       uncompressedSize: 46832,
 
-                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7d\x73\x1c\xb7\xd1\x20\xfe\xbf\x3e\x05\x8a\xcf\xaf\x4a\x24\x6b\x77\x49\x3b\x4f\x12\xff\x78\xa7\x4b\xd1\x92\x9c\xd0\xd6\x0b\x4f\x92\x9d\x4b\xf9\x5c\x59\xec\x4c\xef\x2e\xb4\x33\xc0\x04\xc0\x90\xda\xdc\x73\xdf\xfd\x0a\xdd\x8d\x97\xd9\x5d\x92\x4b\x59\xf4\x85\x57\x4f\xf2\x87\x45\x72\x00\x34\x1a\x8d\x7e\xef\x86\xb7\x52\x79\x77\xf6\x64\x2c\xb4\x6c\xe1\x4c\xc8\xf9\x5c\x69\xe5\xd7\x4f\x84\xe8\x1a\xe9\xe7\xc6\xb6\x67\x
 [...]
+                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x1c\xb7\xb1\xe0\xef\xfe\x2b\x50\x7c\x57\x25\x92\xb5\xbb\x94\x9d\x97\x3c\x1f\xef\x74\x29\x5a\x92\x13\xda\xfa\xe0\x49\xb2\x73\x29\x9f\x2b\x8b\x9d\xe9\xdd\x85\x38\x0b\x4c\x00\x0c\xa9\xcd\xbd\xfb\xdf\xaf\xd0\xdd\xf8\x98\xd9\x5d\x72\x29\x91\x7e\xe1\xd5\x4b\x7e\xb0\x48\x0e\x80\x46\xa3\xd1\xdf\xdd\xf0\x56\x2a\xef\x4e\xbf\x1a\x0b\x2d\x57\x70\x2a\xe4\x7c\xae\xb4\xf2\xeb\xaf\x84\x68\x1b\xe9\xe7\xc6\xae\x4e\xc5\x
 [...]
                },
        }
        fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 26f2b99..a12b261 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -20,9 +20,7 @@ package trait
 import (
        "fmt"
        "path"
-       "sort"
 
-       "github.com/apache/camel-k/pkg/util/defaults"
        appsv1 "k8s.io/api/apps/v1"
        "k8s.io/api/batch/v1beta1"
        corev1 "k8s.io/api/core/v1"
@@ -33,6 +31,7 @@ import (
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util"
+       "github.com/apache/camel-k/pkg/util/defaults"
        "github.com/apache/camel-k/pkg/util/envvar"
        "github.com/apache/camel-k/pkg/util/kubernetes"
 )
@@ -42,7 +41,6 @@ const (
        defaultContainerPort     = 8080
        defaultContainerPortName = "http"
        defaultServicePort       = 80
-       defaultProbePath         = "/q/health"
        containerTraitID         = "container"
 )
 
@@ -82,48 +80,62 @@ type containerTrait struct {
        Image string `property:"image" json:"image,omitempty"`
        // The pull policy: Always|Never|IfNotPresent
        ImagePullPolicy corev1.PullPolicy `property:"image-pull-policy" 
json:"imagePullPolicy,omitempty"`
-       // ProbesEnabled enable/disable probes on the container (default 
`false`)
-       ProbesEnabled *bool `property:"probes-enabled" 
json:"probesEnabled,omitempty"`
+
+       // DeprecatedProbesEnabled enable/disable probes on the container 
(default `false`)
+       // Deprecated: replaced by the health trait.
+       DeprecatedProbesEnabled *bool `property:"probes-enabled" 
json:"probesEnabled,omitempty"`
        // Scheme to use when connecting. Defaults to HTTP. Applies to the 
liveness probe.
-       LivenessScheme string `property:"liveness-scheme" 
json:"livenessScheme,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessScheme string `property:"liveness-scheme" 
json:"livenessScheme,omitempty"`
        // Number of seconds after the container has started before liveness 
probes are initiated.
-       LivenessInitialDelay int32 `property:"liveness-initial-delay" 
json:"livenessInitialDelay,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessInitialDelay int32 `property:"liveness-initial-delay" 
json:"livenessInitialDelay,omitempty"`
        // Number of seconds after which the probe times out. Applies to the 
liveness probe.
-       LivenessTimeout int32 `property:"liveness-timeout" 
json:"livenessTimeout,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessTimeout int32 `property:"liveness-timeout" 
json:"livenessTimeout,omitempty"`
        // How often to perform the probe. Applies to the liveness probe.
-       LivenessPeriod int32 `property:"liveness-period" 
json:"livenessPeriod,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessPeriod int32 `property:"liveness-period" 
json:"livenessPeriod,omitempty"`
        // Minimum consecutive successes for the probe to be considered 
successful after having failed.
        // Applies to the liveness probe.
-       LivenessSuccessThreshold int32 `property:"liveness-success-threshold" 
json:"livenessSuccessThreshold,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessSuccessThreshold int32 
`property:"liveness-success-threshold" 
json:"livenessSuccessThreshold,omitempty"`
        // Minimum consecutive failures for the probe to be considered failed 
after having succeeded.
        // Applies to the liveness probe.
-       LivenessFailureThreshold int32 `property:"liveness-failure-threshold" 
json:"livenessFailureThreshold,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedLivenessFailureThreshold int32 
`property:"liveness-failure-threshold" 
json:"livenessFailureThreshold,omitempty"`
        // Scheme to use when connecting. Defaults to HTTP. Applies to the 
readiness probe.
-       ReadinessScheme string `property:"readiness-scheme" 
json:"readinessScheme,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessScheme string `property:"readiness-scheme" 
json:"readinessScheme,omitempty"`
        // Number of seconds after the container has started before readiness 
probes are initiated.
-       ReadinessInitialDelay int32 `property:"readiness-initial-delay" 
json:"readinessInitialDelay,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessInitialDelay int32 
`property:"readiness-initial-delay" json:"readinessInitialDelay,omitempty"`
        // Number of seconds after which the probe times out. Applies to the 
readiness probe.
-       ReadinessTimeout int32 `property:"readiness-timeout" 
json:"readinessTimeout,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessTimeout int32 `property:"readiness-timeout" 
json:"readinessTimeout,omitempty"`
        // How often to perform the probe. Applies to the readiness probe.
-       ReadinessPeriod int32 `property:"readiness-period" 
json:"readinessPeriod,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessPeriod int32 `property:"readiness-period" 
json:"readinessPeriod,omitempty"`
        // Minimum consecutive successes for the probe to be considered 
successful after having failed.
        // Applies to the readiness probe.
-       ReadinessSuccessThreshold int32 `property:"readiness-success-threshold" 
json:"readinessSuccessThreshold,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessSuccessThreshold int32 
`property:"readiness-success-threshold" 
json:"readinessSuccessThreshold,omitempty"`
        // Minimum consecutive failures for the probe to be considered failed 
after having succeeded.
        // Applies to the readiness probe.
-       ReadinessFailureThreshold int32 `property:"readiness-failure-threshold" 
json:"readinessFailureThreshold,omitempty"`
+       // Deprecated: replaced by the health trait.
+       DeprecatedReadinessFailureThreshold int32 
`property:"readiness-failure-threshold" 
json:"readinessFailureThreshold,omitempty"`
 }
 
 func newContainerTrait() Trait {
        return &containerTrait{
-               BaseTrait:       NewBaseTrait(containerTraitID, 1600),
-               Port:            defaultContainerPort,
-               ServicePort:     defaultServicePort,
-               ServicePortName: defaultContainerPortName,
-               Name:            defaultContainerName,
-               ProbesEnabled:   BoolP(false),
-               LivenessScheme:  string(corev1.URISchemeHTTP),
-               ReadinessScheme: string(corev1.URISchemeHTTP),
+               BaseTrait:                 NewBaseTrait(containerTraitID, 1600),
+               Port:                      defaultContainerPort,
+               ServicePort:               defaultServicePort,
+               ServicePortName:           defaultContainerPortName,
+               Name:                      defaultContainerName,
+               DeprecatedProbesEnabled:   BoolP(false),
+               DeprecatedLivenessScheme:  string(corev1.URISchemeHTTP),
+               DeprecatedReadinessScheme: string(corev1.URISchemeHTTP),
        }
 }
 
@@ -156,18 +168,9 @@ func isValidPullPolicy(policy corev1.PullPolicy) bool {
 
 func (t *containerTrait) Apply(e *Environment) error {
        if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-               if err := t.configureDependencies(e); err != nil {
-                       return err
-               }
-       } else {
-               return t.configureContainer(e)
+               return t.configureImageIntegrationKit(e)
        }
-
-       if err := t.configureImageIntegrationKit(e); err != nil {
-               return err
-       }
-
-       return nil
+       return t.configureContainer(e)
 }
 
 // IsPlatformTrait overrides base class method
@@ -175,21 +178,6 @@ func (t *containerTrait) IsPlatformTrait() bool {
        return true
 }
 
-func (t *containerTrait) configureDependencies(e *Environment) error {
-       if IsTrue(t.ProbesEnabled) {
-               if capability, ok := 
e.CamelCatalog.Runtime.Capabilities[v1.CapabilityHealth]; ok {
-                       for _, dependency := range capability.Dependencies {
-                               
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, 
dependency.GetDependencyID())
-                       }
-
-                       // sort the dependencies to get always the same list if 
they don't change
-                       sort.Strings(e.Integration.Status.Dependencies)
-               }
-       }
-
-       return nil
-}
-
 func (t *containerTrait) configureImageIntegrationKit(e *Environment) error {
        if t.Image != "" {
                if e.Integration.Spec.IntegrationKit != nil {
@@ -269,16 +257,8 @@ func (t *containerTrait) configureContainer(e 
*Environment) error {
        }
        t.configureCapabilities(e)
 
-       portName := t.PortName
-       if portName == "" {
-               portName = defaultContainerPortName
-       }
        // Deployment
        if err := e.Resources.VisitDeploymentE(func(deployment 
*appsv1.Deployment) error {
-               if IsTrue(t.ProbesEnabled) && portName == 
defaultContainerPortName {
-                       t.configureProbes(&container, t.Port, defaultProbePath)
-               }
-
                for _, envVar := range e.EnvVars {
                        envvar.SetVar(&container.Env, envVar)
                }
@@ -302,11 +282,6 @@ func (t *containerTrait) configureContainer(e 
*Environment) error {
 
        // Knative Service
        if err := e.Resources.VisitKnativeServiceE(func(service 
*serving.Service) error {
-               if IsTrue(t.ProbesEnabled) && portName == 
defaultContainerPortName {
-                       // don't set the port on Knative service as it is not 
allowed.
-                       t.configureProbes(&container, 0, defaultProbePath)
-               }
-
                for _, env := range e.EnvVars {
                        switch {
                        case env.ValueFrom == nil:
@@ -341,10 +316,6 @@ func (t *containerTrait) configureContainer(e 
*Environment) error {
 
        // CronJob
        if err := e.Resources.VisitCronJobE(func(cron *v1beta1.CronJob) error {
-               if IsTrue(t.ProbesEnabled) && portName == 
defaultContainerPortName {
-                       t.configureProbes(&container, t.Port, defaultProbePath)
-               }
-
                for _, envVar := range e.EnvVars {
                        envvar.SetVar(&container.Env, envVar)
                }
@@ -462,52 +433,3 @@ func (t *containerTrait) configureCapabilities(e 
*Environment) {
                
e.ApplicationProperties["camel.context.rest-configuration.component"] = 
"platform-http"
        }
 }
-
-func (t *containerTrait) configureProbes(container *corev1.Container, port 
int, path string) {
-       container.LivenessProbe = t.newLivenessProbe(port, path)
-       container.ReadinessProbe = t.newReadinessProbe(port, path)
-}
-
-func (t *containerTrait) newLivenessProbe(port int, path string) *corev1.Probe 
{
-       action := corev1.HTTPGetAction{}
-       action.Path = path
-       action.Scheme = corev1.URIScheme(t.LivenessScheme)
-
-       if port > 0 {
-               action.Port = intstr.FromInt(port)
-       }
-
-       p := corev1.Probe{
-               Handler: corev1.Handler{
-                       HTTPGet: &action,
-               },
-       }
-
-       p.InitialDelaySeconds = t.LivenessInitialDelay
-       p.TimeoutSeconds = t.LivenessTimeout
-       p.PeriodSeconds = t.LivenessPeriod
-       p.SuccessThreshold = t.LivenessSuccessThreshold
-       p.FailureThreshold = t.LivenessFailureThreshold
-
-       return &p
-}
-
-func (t *containerTrait) newReadinessProbe(port int, path string) 
*corev1.Probe {
-       p := corev1.Probe{
-               Handler: corev1.Handler{
-                       HTTPGet: &corev1.HTTPGetAction{
-                               Port:   intstr.FromInt(port),
-                               Path:   path,
-                               Scheme: corev1.URIScheme(t.ReadinessScheme),
-                       },
-               },
-       }
-
-       p.InitialDelaySeconds = t.ReadinessInitialDelay
-       p.TimeoutSeconds = t.ReadinessTimeout
-       p.PeriodSeconds = t.ReadinessPeriod
-       p.SuccessThreshold = t.ReadinessSuccessThreshold
-       p.FailureThreshold = t.ReadinessFailureThreshold
-
-       return &p
-}
diff --git a/pkg/trait/container_probes_test.go 
b/pkg/trait/container_probes_test.go
index cf9ba13..0d4ccbd 100644
--- a/pkg/trait/container_probes_test.go
+++ b/pkg/trait/container_probes_test.go
@@ -22,170 +22,149 @@ import (
 
        "github.com/stretchr/testify/assert"
 
-       serving "knative.dev/serving/pkg/apis/serving/v1"
-
-       appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util/camel"
        "github.com/apache/camel-k/pkg/util/kubernetes"
+       "github.com/apache/camel-k/pkg/util/test"
 )
 
-// nolint: unparam
-func newTestProbesEnv(t *testing.T, provider v1.RuntimeProvider) Environment {
+func newTestProbesEnv(t *testing.T, integration *v1.Integration) Environment {
        t.Helper()
 
-       var catalog *camel.RuntimeCatalog
-       var err error
-
-       switch provider {
-       case v1.RuntimeProviderQuarkus:
-               catalog, err = camel.QuarkusCatalog()
-       default:
-               panic("unknown provider " + provider)
-       }
-
+       catalog, err := camel.DefaultCatalog()
        assert.Nil(t, err)
        assert.NotNil(t, catalog)
 
+       traitCatalog := NewCatalog(nil)
+
        return Environment{
-               CamelCatalog: catalog,
-               Integration: &v1.Integration{
-                       Status: v1.IntegrationStatus{},
-               },
+               Catalog:               traitCatalog,
+               CamelCatalog:          catalog,
+               Platform:              &v1.IntegrationPlatform{},
+               Integration:           integration,
                Resources:             kubernetes.NewCollection(),
                ApplicationProperties: make(map[string]string),
        }
 }
 
-func newTestContainerTrait() *containerTrait {
-       tr, _ := newContainerTrait().(*containerTrait)
-       tr.ProbesEnabled = BoolP(true)
-
-       return tr
-}
+func TestProbesDependencies(t *testing.T) {
+       integration := &v1.Integration{
+               Spec: v1.IntegrationSpec{
+                       Traits: map[string]v1.TraitSpec{
+                               "container": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                       "probesEnabled": true,
+                               }),
+                       },
+               },
+       }
 
-func TestProbesDepsQuarkus(t *testing.T) {
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+       env := newTestProbesEnv(t, integration)
        env.Integration.Status.Phase = v1.IntegrationPhaseInitialization
 
-       ctr := newTestContainerTrait()
-
-       ok, err := ctr.Configure(&env)
+       err := env.Catalog.apply(&env)
        assert.Nil(t, err)
-       assert.True(t, ok)
 
-       err = ctr.Apply(&env)
-       assert.Nil(t, err)
        assert.Contains(t, env.Integration.Status.Dependencies, 
"mvn:org.apache.camel.quarkus:camel-quarkus-microprofile-health")
 }
 
 func TestProbesOnDeployment(t *testing.T) {
-       target := appsv1.Deployment{}
+       integration := &v1.Integration{
+               Spec: v1.IntegrationSpec{
+                       Traits: map[string]v1.TraitSpec{
+                               "container": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                       "probesEnabled":   true,
+                                       "expose":          true,
+                                       "LivenessTimeout": 1234,
+                               }),
+                       },
+               },
+       }
 
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+       env := newTestProbesEnv(t, integration)
        env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
-
-       ctr := newTestContainerTrait()
-       ctr.Expose = BoolP(true)
-       ctr.LivenessTimeout = 1234
 
-       err := ctr.Apply(&env)
+       err := env.Catalog.apply(&env)
        assert.Nil(t, err)
 
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(defaultContainerPort), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
-       assert.Equal(t, corev1.URISchemeHTTP, 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Scheme)
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(defaultContainerPort), 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
-       assert.Equal(t, corev1.URISchemeHTTP, 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Scheme)
-       assert.Equal(t, int32(1234), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
+       container := env.GetIntegrationContainer()
+
+       assert.Equal(t, "", container.LivenessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(defaultContainerPort), 
container.LivenessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultLivenessProbePath, 
container.LivenessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTP, 
container.ReadinessProbe.HTTPGet.Scheme)
+       assert.Equal(t, "", container.ReadinessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(defaultContainerPort), 
container.ReadinessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultReadinessProbePath, 
container.ReadinessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTP, 
container.LivenessProbe.HTTPGet.Scheme)
+       assert.Equal(t, int32(1234), container.LivenessProbe.TimeoutSeconds)
 }
 
 func TestProbesOnDeploymentWithCustomScheme(t *testing.T) {
-       target := appsv1.Deployment{}
+       integration := &v1.Integration{
+               Spec: v1.IntegrationSpec{
+                       Traits: map[string]v1.TraitSpec{
+                               "container": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                       "probesEnabled":   true,
+                                       "expose":          true,
+                                       "livenessTimeout": 1234,
+                                       "livenessScheme":  "HTTPS",
+                                       "readinessScheme": "HTTPS",
+                               }),
+                       },
+               },
+       }
 
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+       env := newTestProbesEnv(t, integration)
        env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
 
-       ctr := newTestContainerTrait()
-       ctr.Expose = BoolP(true)
-       ctr.LivenessTimeout = 1234
-       ctr.LivenessScheme = "HTTPS"
-       ctr.ReadinessScheme = "HTTPS"
-
-       err := ctr.Apply(&env)
+       err := env.Catalog.apply(&env)
        assert.Nil(t, err)
 
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(defaultContainerPort), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
-       assert.Equal(t, corev1.URISchemeHTTPS, 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Scheme)
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(defaultContainerPort), 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
-       assert.Equal(t, corev1.URISchemeHTTPS, 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Scheme)
-       assert.Equal(t, int32(1234), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
-}
-
-func TestProbesOnDeploymentWithNoHttpPort(t *testing.T) {
-       target := appsv1.Deployment{}
-
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
-       env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
-
-       ctr := newTestContainerTrait()
-       ctr.PortName = "custom"
-       ctr.LivenessTimeout = 1234
-
-       err := ctr.Apply(&env)
-       assert.Nil(t, err)
-       assert.Nil(t, target.Spec.Template.Spec.Containers[0].LivenessProbe)
-       assert.Nil(t, target.Spec.Template.Spec.Containers[0].ReadinessProbe)
+       container := env.GetIntegrationContainer()
+
+       assert.Equal(t, "", container.LivenessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(defaultContainerPort), 
container.LivenessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultLivenessProbePath, 
container.LivenessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTPS, 
container.ReadinessProbe.HTTPGet.Scheme)
+       assert.Equal(t, "", container.ReadinessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(defaultContainerPort), 
container.ReadinessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultReadinessProbePath, 
container.ReadinessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTPS, 
container.LivenessProbe.HTTPGet.Scheme)
+       assert.Equal(t, int32(1234), container.LivenessProbe.TimeoutSeconds)
 }
 
 func TestProbesOnKnativeService(t *testing.T) {
-       target := serving.Service{}
+       integration := &v1.Integration{
+               Spec: v1.IntegrationSpec{
+                       Profile: v1.TraitProfileKnative,
+                       Traits: map[string]v1.TraitSpec{
+                               "knative-service": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                       "enabled": true,
+                               }),
+                               "container": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                       "probesEnabled":   true,
+                                       "expose":          true,
+                                       "livenessTimeout": 1234,
+                               }),
+                       },
+               },
+       }
 
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+       env := newTestProbesEnv(t, integration)
        env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
-
-       ctr := newTestContainerTrait()
-       ctr.Expose = BoolP(true)
-       ctr.LivenessTimeout = 1234
 
-       err := ctr.Apply(&env)
+       err := env.Catalog.apply(&env)
        assert.Nil(t, err)
 
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(0), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
-       assert.Equal(t, "", 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
-       assert.Equal(t, int32(0), 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
-       assert.Equal(t, defaultProbePath, 
target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
-       assert.Equal(t, int32(1234), 
target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
-}
-
-func TestProbesOnKnativeServiceWithNoHttpPort(t *testing.T) {
-       target := serving.Service{}
+       container := env.GetIntegrationContainer()
 
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
-       env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
-
-       ctr := newTestContainerTrait()
-       ctr.PortName = "custom"
-       ctr.LivenessTimeout = 1234
-
-       err := ctr.Apply(&env)
-       assert.Nil(t, err)
-       assert.Nil(t, target.Spec.Template.Spec.Containers[0].LivenessProbe)
-       assert.Nil(t, target.Spec.Template.Spec.Containers[0].ReadinessProbe)
+       assert.Equal(t, "", container.LivenessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(0), container.LivenessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultLivenessProbePath, 
container.LivenessProbe.HTTPGet.Path)
+       assert.Equal(t, "", container.ReadinessProbe.HTTPGet.Host)
+       assert.Equal(t, int32(0), container.ReadinessProbe.HTTPGet.Port.IntVal)
+       assert.Equal(t, defaultReadinessProbePath, 
container.ReadinessProbe.HTTPGet.Path)
+       assert.Equal(t, int32(1234), container.LivenessProbe.TimeoutSeconds)
 }
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index f36a0db..c4deae4 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -24,7 +24,6 @@ import (
        "github.com/google/uuid"
        "github.com/stretchr/testify/assert"
 
-       appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/apimachinery/pkg/types"
@@ -331,22 +330,37 @@ func 
TestContainerWithCustomImageAndDeprecatedIntegrationKit(t *testing.T) {
 }
 
 func TestContainerWithImagePullPolicy(t *testing.T) {
-       target := appsv1.Deployment{}
+       catalog, err := camel.DefaultCatalog()
+       assert.Nil(t, err)
 
-       env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
-       env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
-       env.Resources.Add(&target)
+       client, _ := test.NewFakeClient()
+       traitCatalog := NewCatalog(nil)
 
-       ctr := newTestContainerTrait()
-       ctr.ImagePullPolicy = "Always"
+       environment := Environment{
+               Ctx:          context.TODO(),
+               Client:       client,
+               CamelCatalog: catalog,
+               Catalog:      traitCatalog,
+               Integration: &v1.Integration{
+                       Spec: v1.IntegrationSpec{
+                               Profile: v1.TraitProfileKubernetes,
+                               Traits: map[string]v1.TraitSpec{
+                                       "container": test.TraitSpecFromMap(t, 
map[string]interface{}{
+                                               "imagePullPolicy": "Always",
+                                       }),
+                               },
+                       },
+               },
+               Platform:  &v1.IntegrationPlatform{},
+               Resources: kubernetes.NewCollection(),
+       }
+       environment.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+       environment.Platform.ResyncStatusFullConfig()
 
-       err := ctr.Apply(&env)
+       err = traitCatalog.apply(&environment)
        assert.Nil(t, err)
-       assert.Equal(t, corev1.PullAlways, 
target.Spec.Template.Spec.Containers[0].ImagePullPolicy)
 
-       ctr.ImagePullPolicy = "MustFail"
+       container := environment.GetIntegrationContainer()
 
-       ok, err := ctr.Configure(&env)
-       assert.False(t, ok)
-       assert.NotNil(t, err)
+       assert.Equal(t, corev1.PullAlways, container.ImagePullPolicy)
 }
diff --git a/pkg/trait/health.go b/pkg/trait/health.go
new file mode 100644
index 0000000..0d60ca4
--- /dev/null
+++ b/pkg/trait/health.go
@@ -0,0 +1,195 @@
+/*
+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 (
+       "encoding/json"
+       "sort"
+
+       corev1 "k8s.io/api/core/v1"
+       "k8s.io/apimachinery/pkg/util/intstr"
+
+       v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/pkg/util"
+)
+
+const (
+       defaultLivenessProbePath  = "/q/health/live"
+       defaultReadinessProbePath = "/q/health/ready"
+)
+
+// The health trait is responsible for configuring the health probes on the 
integration container.
+//
+// It's disabled by default.
+//
+// +camel-k:trait=health
+type healthTrait struct {
+       BaseTrait `property:",squash"`
+
+       // Configures the liveness probe for the integration container (default 
`false`).
+       LivenessProbeEnabled *bool `property:"liveness-probe-enabled" 
json:"livenessProbeEnabled,omitempty"`
+       // Scheme to use when connecting to the liveness probe (default `HTTP`).
+       LivenessScheme string `property:"liveness-scheme" 
json:"livenessScheme,omitempty"`
+       // Number of seconds after the container has started before the 
liveness probe is initiated.
+       LivenessInitialDelay int32 `property:"liveness-initial-delay" 
json:"livenessInitialDelay,omitempty"`
+       // Number of seconds after which the liveness probe times out.
+       LivenessTimeout int32 `property:"liveness-timeout" 
json:"livenessTimeout,omitempty"`
+       // How often to perform the liveness probe.
+       LivenessPeriod int32 `property:"liveness-period" 
json:"livenessPeriod,omitempty"`
+       // Minimum consecutive successes for the liveness probe to be 
considered successful after having failed.
+       LivenessSuccessThreshold int32 `property:"liveness-success-threshold" 
json:"livenessSuccessThreshold,omitempty"`
+       // Minimum consecutive failures for the liveness probe to be considered 
failed after having succeeded.
+       LivenessFailureThreshold int32 `property:"liveness-failure-threshold" 
json:"livenessFailureThreshold,omitempty"`
+
+       // Configures the readiness probe for the integration container 
(default `true`).
+       ReadinessProbeEnabled *bool `property:"readiness-probe-enabled" 
json:"readinessProbeEnabled,omitempty"`
+       // Scheme to use when connecting to the readiness probe (default 
`HTTP`).
+       ReadinessScheme string `property:"readiness-scheme" 
json:"readinessScheme,omitempty"`
+       // Number of seconds after the container has started before the 
readiness probe is initiated.
+       ReadinessInitialDelay int32 `property:"readiness-initial-delay" 
json:"readinessInitialDelay,omitempty"`
+       // Number of seconds after which the readiness probe times out.
+       ReadinessTimeout int32 `property:"readiness-timeout" 
json:"readinessTimeout,omitempty"`
+       // How often to perform the readiness probe.
+       ReadinessPeriod int32 `property:"readiness-period" 
json:"readinessPeriod,omitempty"`
+       // Minimum consecutive successes for the readiness probe to be 
considered successful after having failed.
+       ReadinessSuccessThreshold int32 `property:"readiness-success-threshold" 
json:"readinessSuccessThreshold,omitempty"`
+       // Minimum consecutive failures for the readiness probe to be 
considered failed after having succeeded.
+       ReadinessFailureThreshold int32 `property:"readiness-failure-threshold" 
json:"readinessFailureThreshold,omitempty"`
+}
+
+func newHealthTrait() Trait {
+       return &healthTrait{
+               BaseTrait:       NewBaseTrait("health", 1700),
+               LivenessScheme:  string(corev1.URISchemeHTTP),
+               ReadinessScheme: string(corev1.URISchemeHTTP),
+       }
+}
+
+func (t *healthTrait) Configure(e *Environment) (bool, error) {
+       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
+               return false, nil
+       }
+
+       if IsNilOrFalse(t.Enabled) {
+               // Source the configuration from the container trait to 
maintain backward compatibility.
+               // This can be removed once the deprecated properties related 
to health probes are actually
+               // removed from the container trait.
+               if trait := e.Catalog.GetTrait(containerTraitID); trait != nil {
+                       if container, ok := trait.(*containerTrait); ok && 
IsNilOrTrue(container.Enabled) && IsTrue(container.DeprecatedProbesEnabled) {
+                               config, err := json.Marshal(container)
+                               if err != nil {
+                                       return false, err
+                               }
+                               err = json.Unmarshal(config, t)
+                               if err != nil {
+                                       return false, err
+                               }
+                               t.Enabled = BoolP(true)
+                               t.LivenessProbeEnabled = BoolP(true)
+                               t.ReadinessProbeEnabled = BoolP(true)
+                               return true, err
+                       }
+               }
+               return false, nil
+       }
+
+       return true, nil
+}
+
+func (t *healthTrait) Apply(e *Environment) error {
+       if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+               if capability, ok := 
e.CamelCatalog.Runtime.Capabilities[v1.CapabilityHealth]; ok {
+                       for _, dependency := range capability.Dependencies {
+                               
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, 
dependency.GetDependencyID())
+                       }
+                       // sort the dependencies to get always the same list if 
they don't change
+                       sort.Strings(e.Integration.Status.Dependencies)
+               }
+               return nil
+       }
+
+       if IsNilOrFalse(t.LivenessProbeEnabled) && 
IsFalse(t.ReadinessProbeEnabled) {
+               return nil
+       }
+
+       container := e.GetIntegrationContainer()
+       var port *intstr.IntOrString
+       // Use the default named HTTP container port if it exists.
+       // For Knative, the Serving webhook is responsible for setting the 
user-land port,
+       // and associating the probes with the corresponding port.
+       if containerPort := e.getIntegrationContainerPort(); containerPort != 
nil && containerPort.Name == defaultContainerPortName {
+               p := intstr.FromString(defaultContainerPortName)
+               port = &p
+       } else if e.GetTrait(knativeServiceTraitID) == nil {
+               p := intstr.FromInt(defaultContainerPort)
+               port = &p
+       }
+
+       if IsTrue(t.LivenessProbeEnabled) {
+               container.LivenessProbe = t.newLivenessProbe(port, 
defaultLivenessProbePath)
+       }
+       if IsNilOrTrue(t.ReadinessProbeEnabled) {
+               container.ReadinessProbe = t.newReadinessProbe(port, 
defaultReadinessProbePath)
+       }
+
+       return nil
+}
+
+func (t *healthTrait) newLivenessProbe(port *intstr.IntOrString, path string) 
*corev1.Probe {
+       p := corev1.Probe{
+               Handler: corev1.Handler{
+                       HTTPGet: &corev1.HTTPGetAction{
+                               Path:   path,
+                               Scheme: corev1.URIScheme(t.LivenessScheme),
+                       },
+               },
+               InitialDelaySeconds: t.LivenessInitialDelay,
+               TimeoutSeconds:      t.LivenessTimeout,
+               PeriodSeconds:       t.LivenessPeriod,
+               SuccessThreshold:    t.LivenessSuccessThreshold,
+               FailureThreshold:    t.LivenessFailureThreshold,
+       }
+
+       if port != nil {
+               p.Handler.HTTPGet.Port = *port
+       }
+
+       return &p
+}
+
+func (t *healthTrait) newReadinessProbe(port *intstr.IntOrString, path string) 
*corev1.Probe {
+       p := corev1.Probe{
+               Handler: corev1.Handler{
+                       HTTPGet: &corev1.HTTPGetAction{
+                               Path:   path,
+                               Scheme: corev1.URIScheme(t.ReadinessScheme),
+                       },
+               },
+               InitialDelaySeconds: t.ReadinessInitialDelay,
+               TimeoutSeconds:      t.ReadinessTimeout,
+               PeriodSeconds:       t.ReadinessPeriod,
+               SuccessThreshold:    t.ReadinessSuccessThreshold,
+               FailureThreshold:    t.ReadinessFailureThreshold,
+       }
+
+       if port != nil {
+               p.Handler.HTTPGet.Port = *port
+       }
+
+       return &p
+}
diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go
index 819f9de..b96a70d 100644
--- a/pkg/trait/jolokia.go
+++ b/pkg/trait/jolokia.go
@@ -99,7 +99,7 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) {
                return nil
        }
 
-       container := e.getIntegrationContainer()
+       container := e.GetIntegrationContainer()
        if container == nil {
                e.Integration.Status.SetCondition(
                        v1.IntegrationConditionJolokiaAvailable,
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 7810cc7..7d1991a 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -132,7 +132,7 @@ func (t *jvmTrait) Apply(e *Environment) error {
                )
        }
 
-       container := e.getIntegrationContainer()
+       container := e.GetIntegrationContainer()
        if container == nil {
                return nil
        }
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index bc47aac..4360692 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -201,7 +201,7 @@ func TestApplyJvmTraitWithExternalKitType(t *testing.T) {
        err := trait.Apply(environment)
        assert.Nil(t, err)
 
-       container := environment.getIntegrationContainer()
+       container := environment.GetIntegrationContainer()
 
        assert.Equal(t, 3, len(container.Args))
        assert.Equal(t, "-cp", container.Args[0])
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index 7859e08..2b01dd1 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -33,6 +33,8 @@ import (
 )
 
 const (
+       knativeServiceTraitID = "knative-service"
+
        // Auto-scaling annotations
        knativeServingClassAnnotation    = "autoscaling.knative.dev/class"
        knativeServingMetricAnnotation   = "autoscaling.knative.dev/metric"
@@ -89,7 +91,7 @@ var _ ControllerStrategySelector = &knativeServiceTrait{}
 
 func newKnativeServiceTrait() Trait {
        return &knativeServiceTrait{
-               BaseTrait: NewBaseTrait("knative-service", 1400),
+               BaseTrait: NewBaseTrait(knativeServiceTraitID, 1400),
        }
 }
 
diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go
index 6db5c51..9dae4c8 100644
--- a/pkg/trait/prometheus.go
+++ b/pkg/trait/prometheus.go
@@ -71,7 +71,7 @@ func (t *prometheusTrait) Apply(e *Environment) (err error) {
                return nil
        }
 
-       container := e.getIntegrationContainer()
+       container := e.GetIntegrationContainer()
        if container == nil {
                e.Integration.Status.SetCondition(
                        v1.IntegrationConditionPrometheusAvailable,
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
index 4881d7d..c1c37b6 100644
--- a/pkg/trait/quarkus.go
+++ b/pkg/trait/quarkus.go
@@ -235,7 +235,7 @@ func (t *quarkusTrait) Apply(e *Environment) error {
 
        case v1.IntegrationKitPhaseReady:
                if e.IntegrationInRunningPhases() && t.isNativeIntegration(e) {
-                       container := e.getIntegrationContainer()
+                       container := e.GetIntegrationContainer()
                        if container == nil {
                                return fmt.Errorf("unable to find integration 
container: %s", e.Integration.Name)
                        }
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index 64e8a39..68d2997 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -31,6 +31,7 @@ func init() {
        AddToTraits(newEnvironmentTrait)
        AddToTraits(newErrorHandlerTrait)
        AddToTraits(newGarbageCollectorTrait)
+       AddToTraits(newHealthTrait)
        AddToTraits(newIngressTrait)
        AddToTraits(newIstioTrait)
        AddToTraits(newJolokiaTrait)
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index b0b0241..d4993b9 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -747,7 +747,7 @@ func (e *Environment) 
collectConfigurations(configurationType string) []map[stri
        return collectConfigurations(configurationType, e.Platform, 
e.IntegrationKit, e.Integration)
 }
 
-func (e *Environment) getIntegrationContainer() *corev1.Container {
+func (e *Environment) GetIntegrationContainer() *corev1.Container {
        containerName := defaultContainerName
        dt := e.Catalog.GetTrait(containerTraitID)
        if dt != nil {
@@ -758,7 +758,7 @@ func (e *Environment) getIntegrationContainer() 
*corev1.Container {
 }
 
 func (e *Environment) getIntegrationContainerPort() *corev1.ContainerPort {
-       container := e.getIntegrationContainer()
+       container := e.GetIntegrationContainer()
        if container == nil {
                return nil
        }
diff --git a/resources/traits.yaml b/resources/traits.yaml
index f314b60..47ffab4 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -134,53 +134,60 @@ traits:
     description: 'The pull policy: Always|Never|IfNotPresent'
   - name: probes-enabled
     type: bool
-    description: ProbesEnabled enable/disable probes on the container (default 
`false`)
+    description: 'DeprecatedProbesEnabled enable/disable probes on the 
container (default
+      `false`)Deprecated: replaced by the health trait.'
   - name: liveness-scheme
     type: string
-    description: Scheme to use when connecting. Defaults to HTTP. Applies to 
the liveness
-      probe.
+    description: 'Scheme to use when connecting. Defaults to HTTP. Applies to 
the
+      liveness probe.Deprecated: replaced by the health trait.'
   - name: liveness-initial-delay
     type: int32
-    description: Number of seconds after the container has started before 
liveness
-      probes are initiated.
+    description: 'Number of seconds after the container has started before 
liveness
+      probes are initiated.Deprecated: replaced by the health trait.'
   - name: liveness-timeout
     type: int32
-    description: Number of seconds after which the probe times out. Applies to 
the
-      liveness probe.
+    description: 'Number of seconds after which the probe times out. Applies 
to the
+      liveness probe.Deprecated: replaced by the health trait.'
   - name: liveness-period
     type: int32
-    description: How often to perform the probe. Applies to the liveness probe.
+    description: 'How often to perform the probe. Applies to the liveness 
probe.Deprecated:
+      replaced by the health trait.'
   - name: liveness-success-threshold
     type: int32
-    description: Minimum consecutive successes for the probe to be considered 
successful
-      after having failed.Applies to the liveness probe.
+    description: 'Minimum consecutive successes for the probe to be considered 
successful
+      after having failed.Applies to the liveness probe.Deprecated: replaced 
by the
+      health trait.'
   - name: liveness-failure-threshold
     type: int32
-    description: Minimum consecutive failures for the probe to be considered 
failed
-      after having succeeded.Applies to the liveness probe.
+    description: 'Minimum consecutive failures for the probe to be considered 
failed
+      after having succeeded.Applies to the liveness probe.Deprecated: 
replaced by
+      the health trait.'
   - name: readiness-scheme
     type: string
-    description: Scheme to use when connecting. Defaults to HTTP. Applies to 
the readiness
-      probe.
+    description: 'Scheme to use when connecting. Defaults to HTTP. Applies to 
the
+      readiness probe.Deprecated: replaced by the health trait.'
   - name: readiness-initial-delay
     type: int32
-    description: Number of seconds after the container has started before 
readiness
-      probes are initiated.
+    description: 'Number of seconds after the container has started before 
readiness
+      probes are initiated.Deprecated: replaced by the health trait.'
   - name: readiness-timeout
     type: int32
-    description: Number of seconds after which the probe times out. Applies to 
the
-      readiness probe.
+    description: 'Number of seconds after which the probe times out. Applies 
to the
+      readiness probe.Deprecated: replaced by the health trait.'
   - name: readiness-period
     type: int32
-    description: How often to perform the probe. Applies to the readiness 
probe.
+    description: 'How often to perform the probe. Applies to the readiness 
probe.Deprecated:
+      replaced by the health trait.'
   - name: readiness-success-threshold
     type: int32
-    description: Minimum consecutive successes for the probe to be considered 
successful
-      after having failed.Applies to the readiness probe.
+    description: 'Minimum consecutive successes for the probe to be considered 
successful
+      after having failed.Applies to the readiness probe.Deprecated: replaced 
by the
+      health trait.'
   - name: readiness-failure-threshold
     type: int32
-    description: Minimum consecutive failures for the probe to be considered 
failed
-      after having succeeded.Applies to the readiness probe.
+    description: 'Minimum consecutive failures for the probe to be considered 
failed
+      after having succeeded.Applies to the readiness probe.Deprecated: 
replaced by
+      the health trait.'
 - name: cron
   platform: false
   profiles:
@@ -345,6 +352,69 @@ traits:
     type: ./pkg/trait.discoveryCacheType
     description: Discovery client cache to be used, either `disabled`, `disk` 
or `memory`
       (default `memory`)
+- name: health
+  platform: false
+  profiles:
+  - Kubernetes
+  - Knative
+  - OpenShift
+  description: The health trait is responsible for configuring the health 
probes on
+    the integration container. It's disabled by default.
+  properties:
+  - name: enabled
+    type: bool
+    description: Can be used to enable or disable a trait. All traits share 
this common
+      property.
+  - name: liveness-probe-enabled
+    type: bool
+    description: Configures the liveness probe for the integration container 
(default
+      `false`).
+  - name: liveness-scheme
+    type: string
+    description: Scheme to use when connecting to the liveness probe (default 
`HTTP`).
+  - name: liveness-initial-delay
+    type: int32
+    description: Number of seconds after the container has started before the 
liveness
+      probe is initiated.
+  - name: liveness-timeout
+    type: int32
+    description: Number of seconds after which the liveness probe times out.
+  - name: liveness-period
+    type: int32
+    description: How often to perform the liveness probe.
+  - name: liveness-success-threshold
+    type: int32
+    description: Minimum consecutive successes for the liveness probe to be 
considered
+      successful after having failed.
+  - name: liveness-failure-threshold
+    type: int32
+    description: Minimum consecutive failures for the liveness probe to be 
considered
+      failed after having succeeded.
+  - name: readiness-probe-enabled
+    type: bool
+    description: Configures the readiness probe for the integration container 
(default
+      `true`).
+  - name: readiness-scheme
+    type: string
+    description: Scheme to use when connecting to the readiness probe (default 
`HTTP`).
+  - name: readiness-initial-delay
+    type: int32
+    description: Number of seconds after the container has started before the 
readiness
+      probe is initiated.
+  - name: readiness-timeout
+    type: int32
+    description: Number of seconds after which the readiness probe times out.
+  - name: readiness-period
+    type: int32
+    description: How often to perform the readiness probe.
+  - name: readiness-success-threshold
+    type: int32
+    description: Minimum consecutive successes for the readiness probe to be 
considered
+      successful after having failed.
+  - name: readiness-failure-threshold
+    type: int32
+    description: Minimum consecutive failures for the readiness probe to be 
considered
+      failed after having succeeded.
 - name: ingress
   platform: false
   profiles:

Reply via email to