You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2020/03/13 15:41:28 UTC
[camel-k] branch master updated: Probes not bound to Knative
services #1341
This is an automated email from the ASF dual-hosted git repository.
nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/master by this push:
new 7046da6 Probes not bound to Knative services #1341
7046da6 is described below
commit 7046da68955d9fd5d1bb8e807933e065dffcb0d7
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Fri Mar 13 00:16:44 2020 +0100
Probes not bound to Knative services #1341
---
deploy/camel-catalog-1.2.0-SNAPSHOT-main.yaml | 2 +
deploy/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml | 12 +-
deploy/resources.go | 8 +-
docs/modules/ROOT/nav.adoc | 1 -
docs/modules/ROOT/pages/traits/probes.adoc | 81 --------
docs/modules/ROOT/pages/traits/traits.adoc | 1 -
e2e/openapi_test.go | 4 +-
go.sum | 3 +
pkg/apis/camel/v1/integration_types.go | 4 +
pkg/trait/container.go | 242 ++++++++++++++++++++---
pkg/trait/container_probes_test.go | 190 ++++++++++++++++++
pkg/trait/probes.go | 170 ----------------
pkg/trait/probes_test.go | 186 -----------------
pkg/trait/trait_register.go | 1 -
pkg/trait/trait_types.go | 48 ++---
pkg/util/kubernetes/collection.go | 51 ++++-
16 files changed, 503 insertions(+), 501 deletions(-)
diff --git a/deploy/camel-catalog-1.2.0-SNAPSHOT-main.yaml b/deploy/camel-catalog-1.2.0-SNAPSHOT-main.yaml
index 50d1907..4faa5e4 100644
--- a/deploy/camel-catalog-1.2.0-SNAPSHOT-main.yaml
+++ b/deploy/camel-catalog-1.2.0-SNAPSHOT-main.yaml
@@ -3095,6 +3095,8 @@ spec:
- groupId: org.apache.camel.k
artifactId: camel-knative-api
- groupId: org.apache.camel.k
+ artifactId: camel-knative
+ - groupId: org.apache.camel.k
artifactId: camel-knative-http
loaders:
yaml:
diff --git a/deploy/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml b/deploy/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml
index e1f820f..31a8c4f 100644
--- a/deploy/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml
+++ b/deploy/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml
@@ -819,13 +819,9 @@ spec:
artifactId: camel-k-runtime-knative
dependencies:
- groupId: org.apache.camel.k
- artifactId: camel-k-loader-yaml
+ artifactId: camel-k-quarkus-knative
- groupId: org.apache.camel.k
- artifactId: camel-knative-api
- - groupId: org.apache.camel.k
- artifactId: camel-knative
- - groupId: org.apache.camel.k
- artifactId: camel-knative-http
+ artifactId: camel-k-quarkus-loader-yaml
camel-knative:
groupId: org.apache.camel.k
artifactId: camel-knative
@@ -835,9 +831,7 @@ spec:
passive: false
dependencies:
- groupId: org.apache.camel.k
- artifactId: camel-knative-api
- - groupId: org.apache.camel.k
- artifactId: camel-knative-http
+ artifactId: camel-k-quarkus-knative
loaders:
yaml:
groupId: org.apache.camel.k
diff --git a/deploy/resources.go b/deploy/resources.go
index 4f68dc8..4d1a345 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -91,16 +91,16 @@ var assets = func() http.FileSystem {
"/camel-catalog-1.2.0-SNAPSHOT-main.yaml": &vfsgen۰CompressedFileInfo{
name: "camel-catalog-1.2.0-SNAPSHOT-main.yaml",
modTime: time.Time{},
- uncompressedSize: 87168,
+ uncompressedSize: 87238,
- compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x7d\x5b\x77\xdb\x38\xb2\xee\x7b\x7e\x05\xd7\xe4\x65\xef\x75\x46\x98\x6e\x67\xf6\xf4\xd9\x7d\x9e\x6c\x39\x4e\xec\xd8\x8e\x3b\xf4\x24\x99\x7e\xe9\x05\x91\x90\x04\x8b\x24\x68\x00\x92\x65\xff\xfa\xb3\x70\xe1\x55\x10\x24\xb2\x0c\xfb\xc1\xa4\x88\xaa\xaf\x58\x00\x88\x6b\xa1\xea\x7d\x34\x79\xbd\xbf\x77\xef\xa3\x6b\x9a\x90\x42\x90\x34\x92\x2c\x92\x4b\x12\x9d\x96\x38\x59\x92\x28\x66\x73\xf9\x84\x39\x89\x2e\xd8\xba\x48\xb1\x [...]
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xbd\x5b\x77\xdb\x38\xb2\x2f\xfe\x9e\x4f\xc1\x35\x79\xd9\x7b\xfd\x47\x98\x6e\x67\xf6\xf4\x7f\xf7\x79\xb2\xe5\x38\xb1\x63\x3b\xee\xd0\x93\x64\xfa\xa5\x17\x44\x42\x12\x2c\x92\xa0\x01\x48\x96\xfd\xe9\xcf\xc2\x85\x57\x41\x90\xc8\x32\xbc\x8e\x1f\x4c\x8a\xa8\xfa\x15\x0b\x00\x71\x2d\x54\xbd\x8f\x26\xaf\xf7\xf7\xee\x7d\x74\x4d\x13\x52\x08\x92\x46\x92\x45\x72\x49\xa2\xd3\x12\x27\x4b\x12\xc5\x6c\x2e\x9f\x30\x27\xd1\x05\x5b\x [...]
},
"/camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml": &vfsgen۰CompressedFileInfo{
name: "camel-catalog-1.2.0-SNAPSHOT-quarkus.yaml",
modTime: time.Time{},
- uncompressedSize: 26457,
+ uncompressedSize: 26257,
- compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x5c\x5b\x77\xdb\xa8\xf6\x7f\xf7\xa7\x60\x35\x2f\xe7\xac\x55\xd1\x4e\x33\x33\x0f\xf9\x3f\x25\x69\x32\x4d\x9b\xdb\x3f\xf2\xb4\x9d\x79\xc3\x12\x96\x88\x25\x50\x00\x5f\x92\x4f\x7f\x16\x08\x5d\xa3\x20\xc9\x46\xcd\x43\x2c\x8b\xbd\x7f\xfb\x86\x60\xb3\x85\x39\x02\x9e\xbb\xbf\xd9\x11\xb8\x26\x01\xa6\x02\x87\x40\x32\x20\x63\x0c\x4e\x33\x14\xc4\x18\xf8\x6c\x29\xb7\x88\x63\x70\xc9\xd6\x34\x44\x92\x30\x0a\xfe\x73\xea\x5f\xfe\x [...]
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x5c\xcb\x76\xdb\x38\xd2\xde\xeb\x29\x70\xe2\xcd\xcc\x39\x4d\x24\x1d\xcf\xf4\xc2\xff\xca\x76\xec\x8e\x13\xdf\xfe\x50\x9d\xa4\x7b\x07\x91\x25\x11\x16\x09\xd0\x00\x74\xb1\x9f\x7e\x0e\x40\xf0\x22\x99\x06\x49\x19\x8c\x17\x16\x45\x54\x7d\x75\x01\x08\x14\x8a\x25\x1c\xa1\xc0\xdf\xdf\xe4\x08\x5d\xd3\x08\x98\x84\x18\x29\x8e\x54\x02\xe8\x34\x27\x51\x02\x28\xe4\x73\xb5\x21\x02\xd0\x25\x5f\xb1\x98\x28\xca\x19\xfa\xd7\x69\x78\x [...]
},
"/cr-example.yaml": &vfsgen۰CompressedFileInfo{
name: "cr-example.yaml",
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index efbf12e..9a7f96b 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -35,7 +35,6 @@
** xref:traits/master.adoc[Master]
** xref:traits/owner.adoc[Owner]
** xref:traits/platform.adoc[Platform]
-** xref:traits/probes.adoc[Probes]
** xref:traits/prometheus.adoc[Prometheus]
** xref:traits/pull-secret.adoc[Pull Secret]
** xref:traits/quarkus.adoc[Quarkus]
diff --git a/docs/modules/ROOT/pages/traits/probes.adoc b/docs/modules/ROOT/pages/traits/probes.adoc
deleted file mode 100755
index 3d2dbaf..0000000
--- a/docs/modules/ROOT/pages/traits/probes.adoc
+++ /dev/null
@@ -1,81 +0,0 @@
-= Probes Trait
-
-// Start of autogenerated code - DO NOT EDIT! (description)
-The Probes trait allows to configure Liveness and Readiness probes on the integration container.
-
-
-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:
-```
-kamel run --trait probes.[key]=[value] --trait probes.[key2]=[value2] integration.groovy
-```
-The following configuration options are available:
-
-[cols="2,1,5a"]
-|===
-|Property | Type | Description
-
-| probes.enabled
-| bool
-| Can be used to enable or disable a trait. All traits share this common property.
-
-| probes.bind-host
-| string
-| Configures the host on which the probe is exposed (default `0.0.0.0`).
-
-| probes.bind-port
-| int
-| Configures the port on which the probe is exposed (default `8080`).
-
-| probes.path
-| string
-| Path to access on the probe ( default `/health`).
-
-| probes.liveness-initial-delay
-| int32
-| Number of seconds after the container has started before liveness probes are initiated.
-
-| probes.liveness-timeout
-| int32
-| Number of seconds after which the probe times out. Applies to the liveness probe.
-
-| probes.liveness-period
-| int32
-| How often to perform the probe. Applies to the liveness probe.
-
-| probes.liveness-success-threshold
-| int32
-| Minimum consecutive successes for the probe to be considered successful after having failed. Applies to the liveness probe.
-
-| probes.liveness-failure-threshold
-| int32
-| Minimum consecutive failures for the probe to be considered failed after having succeeded. Applies to the liveness probe.
-
-| probes.readiness-initial-delay
-| int32
-| Number of seconds after the container has started before readiness probes are initiated.
-
-| probes.readiness-timeout
-| int32
-| Number of seconds after which the probe times out. Applies to the readiness probe.
-
-| probes.readiness-period
-| int32
-| How often to perform the probe. Applies to the readiness probe.
-
-| probes.readiness-success-threshold
-| int32
-| Minimum consecutive successes for the probe to be considered successful after having failed. Applies to the readiness probe.
-
-| probes.readiness-failure-threshold
-| int32
-| Minimum consecutive failures for the probe to be considered failed after having succeeded. Applies to the readiness probe.
-
-|===
-
-// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/docs/modules/ROOT/pages/traits/traits.adoc b/docs/modules/ROOT/pages/traits/traits.adoc
index 8109aea..fac82b1 100644
--- a/docs/modules/ROOT/pages/traits/traits.adoc
+++ b/docs/modules/ROOT/pages/traits/traits.adoc
@@ -53,7 +53,6 @@ See the trait description pages for more information on a specific trait:
* xref:traits/master.adoc[Master Trait]
* xref:traits/owner.adoc[Owner Trait]
* xref:traits/platform.adoc[Platform Trait]
-* xref:traits/probes.adoc[Probes Trait]
* xref:traits/prometheus.adoc[Prometheus Trait]
* xref:traits/pull-secret.adoc[Pull Secret Trait]
* xref:traits/quarkus.adoc[Quarkus Trait]
diff --git a/e2e/openapi_test.go b/e2e/openapi_test.go
index e4fb0c0..735603f 100644
--- a/e2e/openapi_test.go
+++ b/e2e/openapi_test.go
@@ -31,7 +31,7 @@ import (
)
func TestOpenAPIService(t *testing.T) {
- withNewTestNamespaceWithKnativeBroker(t, func(ns string) {
+ withNewTestNamespace(t, func(ns string) {
Expect(kamel("install", "-n", ns, "--trait-profile", string(v1.TraitProfileKnative)).Execute()).Should(BeNil())
Expect(kamel(
"run",
@@ -56,7 +56,7 @@ func TestOpenAPIService(t *testing.T) {
}
func TestOpenAPIDeployment(t *testing.T) {
- withNewTestNamespaceWithKnativeBroker(t, func(ns string) {
+ withNewTestNamespace(t, func(ns string) {
Expect(kamel("install", "-n", ns, "--trait-profile", string(v1.TraitProfileKubernetes)).Execute()).Should(BeNil())
Expect(kamel(
"run",
diff --git a/go.sum b/go.sum
index 188bbe4..149e0cc 100644
--- a/go.sum
+++ b/go.sum
@@ -148,6 +148,7 @@ github.com/containerd/console v0.0.0-20170925154832-84eeaae905fa/go.mod h1:Tj/on
github.com/containerd/containerd v1.0.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-beta.2.0.20190823190603-4a2f61c4f2b4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -199,11 +200,13 @@ github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017 h1:2HQmlpI3yI9deH18Q6xi
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go
index c1d5efd..2be9742 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -191,6 +191,8 @@ const (
IntegrationConditionPrometheusAvailable IntegrationConditionType = "PrometheusAvailable"
// IntegrationConditionJolokiaAvailable --
IntegrationConditionJolokiaAvailable IntegrationConditionType = "JolokiaAvailable"
+ // IntegrationConditionProbesAvailable --
+ IntegrationConditionProbesAvailable IntegrationConditionType = "ProbesAvailable"
// IntegrationConditionKitAvailableReason --
IntegrationConditionKitAvailableReason string = "IntegrationKitAvailable"
@@ -226,6 +228,8 @@ const (
IntegrationConditionPrometheusAvailableReason string = "PrometheusAvailable"
// IntegrationConditionJolokiaAvailableReason --
IntegrationConditionJolokiaAvailableReason string = "JolokiaAvailable"
+ // IntegrationConditionProbesAvailableReason --
+ IntegrationConditionProbesAvailableReason string = "ProbesAvailable"
)
// IntegrationCondition describes the state of a resource at a certain point.
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index d7f9eca..416e844 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -19,8 +19,12 @@ package trait
import (
"fmt"
+ "sort"
+ "strconv"
"strings"
+ "github.com/apache/camel-k/pkg/util"
+
appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"
@@ -35,6 +39,10 @@ import (
const (
defaultContainerName = "integration"
+ defaultContainerPort = 8080
+ defaultServicePort = 80
+ defaultProbePort = 8081
+ defaultProbePath = "/health"
containerTraitID = "container"
)
@@ -47,6 +55,7 @@ type containerTrait struct {
BaseTrait `property:",squash"`
Auto *bool `property:"auto"`
+
// The minimum amount of CPU required.
RequestCPU string `property:"request-cpu"`
// The minimum amount of memory required.
@@ -55,6 +64,7 @@ type containerTrait struct {
LimitCPU string `property:"limit-cpu"`
// The maximum amount of memory required.
LimitMemory string `property:"limit-memory"`
+
// Can be used to enable/disable exposure via kubernetes Service.
Expose *bool `property:"expose"`
// To configure a different port exposed by the container (default `8080`).
@@ -65,18 +75,56 @@ type containerTrait struct {
ServicePort int `property:"service-port"`
// To configure under which service port name the container port is to be exposed (default `http`).
ServicePortName string `property:"service-port-name"`
+
// The main container name. It's named `integration` by default.
Name string `property:"name"`
+
+ // ProbesEnabled enable/disable probes on the container (default `false`)
+ ProbesEnabled bool `property:"probes-enabled"`
+ // ProbePort configures the port on which the probes are exposed if the container is not exposed
+ // through an `http` port (default `8081`). Note that the value has no effect for Knative service
+ // as the port should be the same as the port declared by the container.
+ ProbePort int `property:"probe-port"`
+ // Path to access on the probe ( default `/health`). Note that this property is not supported
+ // on quarkus runtime and setting it will result in the integration failing to start.
+ ProbePath string `property:"probe-path"`
+ // Number of seconds after the container has started before liveness probes are initiated.
+ LivenessInitialDelay int32 `property:"liveness-initial-delay"`
+ // Number of seconds after which the probe times out. Applies to the liveness probe.
+ LivenessTimeout int32 `property:"liveness-timeout"`
+ // How often to perform the probe. Applies to the liveness probe.
+ LivenessPeriod int32 `property:"liveness-period"`
+ // Minimum consecutive successes for the probe to be considered successful after having failed.
+ // Applies to the liveness probe.
+ LivenessSuccessThreshold int32 `property:"liveness-success-threshold"`
+ // Minimum consecutive failures for the probe to be considered failed after having succeeded.
+ // Applies to the liveness probe.
+ LivenessFailureThreshold int32 `property:"liveness-failure-threshold"`
+ // Number of seconds after the container has started before readiness probes are initiated.
+ ReadinessInitialDelay int32 `property:"readiness-initial-delay"`
+ // Number of seconds after which the probe times out. Applies to the readiness probe.
+ ReadinessTimeout int32 `property:"readiness-timeout"`
+ // How often to perform the probe. Applies to the readiness probe.
+ ReadinessPeriod int32 `property:"readiness-period"`
+ // Minimum consecutive successes for the probe to be considered successful after having failed.
+ // Applies to the readiness probe.
+ ReadinessSuccessThreshold int32 `property:"readiness-success-threshold"`
+ // Minimum consecutive failures for the probe to be considered failed after having succeeded.
+ // Applies to the readiness probe.
+ ReadinessFailureThreshold int32 `property:"readiness-failure-threshold"`
}
func newContainerTrait() Trait {
return &containerTrait{
BaseTrait: NewBaseTrait(containerTraitID, 1600),
- Port: 8080,
+ Port: defaultContainerPort,
PortName: httpPortName,
- ServicePort: 80,
+ ServicePort: defaultServicePort,
ServicePortName: httpPortName,
Name: defaultContainerName,
+ ProbesEnabled: false,
+ ProbePort: defaultProbePort,
+ ProbePath: defaultProbePath,
}
}
@@ -85,7 +133,7 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) {
return false, nil
}
- if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+ if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
return false, nil
}
@@ -100,6 +148,40 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) {
}
func (t *containerTrait) Apply(e *Environment) error {
+ if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+ t.configureDependencies(e)
+ }
+
+ if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+ return t.configureContainer(e)
+ }
+
+ return nil
+}
+
+// IsPlatformTrait overrides base class method
+func (t *containerTrait) IsPlatformTrait() bool {
+ return true
+}
+
+func (t *containerTrait) configureDependencies(e *Environment) {
+ if !t.ProbesEnabled {
+ return
+ }
+
+ if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+ if capability, ok := e.CamelCatalog.Runtime.Capabilities["health"]; ok {
+ for _, dependency := range capability.Dependencies {
+ util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
+ }
+
+ // sort the dependencies to get always the same list if they don't change
+ sort.Strings(e.Integration.Status.Dependencies)
+ }
+ }
+}
+
+func (t *containerTrait) configureContainer(e *Environment) error {
container := corev1.Container{
Name: t.Name,
Image: e.Integration.Status.Image,
@@ -118,7 +200,17 @@ func (t *containerTrait) Apply(e *Environment) error {
t.configureResources(e, &container)
- e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
+ if t.Expose != nil && *t.Expose {
+ t.configureService(e, &container)
+ }
+ if props := e.ComputeApplicationProperties(); props != nil {
+ e.Resources.Add(props)
+ }
+
+ //
+ // Deployment
+ //
+ if err := e.Resources.VisitDeploymentE(func(deployment *appsv1.Deployment) error {
for _, envVar := range e.EnvVars {
envvar.SetVar(&container.Env, envVar)
}
@@ -128,10 +220,26 @@ func (t *containerTrait) Apply(e *Environment) error {
&container.VolumeMounts,
)
+ port := t.Port
+ if t.PortName != httpPortName {
+ port = t.ProbePort
+ }
+
+ if err := t.configureProbes(e, &container, port, t.ProbePath); err != nil {
+ return err
+ }
+
deployment.Spec.Template.Spec.Containers = append(deployment.Spec.Template.Spec.Containers, container)
- })
- e.Resources.VisitKnativeService(func(service *serving.Service) {
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ //
+ // Knative Service
+ //
+ if err := e.Resources.VisitKnativeServiceE(func(service *serving.Service) error {
for _, env := range e.EnvVars {
switch {
case env.ValueFrom == nil:
@@ -152,10 +260,22 @@ func (t *containerTrait) Apply(e *Environment) error {
&container.VolumeMounts,
)
+ // don't set the port on Knative service as it is not allowed.
+ if err := t.configureProbes(e, &container, 0, t.ProbePath); err != nil {
+ return err
+ }
+
service.Spec.ConfigurationSpec.Template.Spec.Containers = append(service.Spec.ConfigurationSpec.Template.Spec.Containers, container)
- })
- e.Resources.VisitCronJob(func(cron *v1beta1.CronJob) {
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ //
+ // CronJob
+ //
+ if err := e.Resources.VisitCronJobE(func(cron *v1beta1.CronJob) error {
for _, envVar := range e.EnvVars {
envvar.SetVar(&container.Env, envVar)
}
@@ -165,32 +285,31 @@ func (t *containerTrait) Apply(e *Environment) error {
&container.VolumeMounts,
)
+ port := t.Port
+ if t.PortName != httpPortName {
+ port = t.ProbePort
+ }
+
+ if err := t.configureProbes(e, &container, port, t.ProbePath); err != nil {
+ return err
+ }
+
cron.Spec.JobTemplate.Spec.Template.Spec.Containers = append(cron.Spec.JobTemplate.Spec.Template.Spec.Containers, container)
- })
- if t.Expose != nil && *t.Expose {
- t.configureService(e)
+ return nil
+ }); err != nil {
+ return err
}
return nil
}
-// IsPlatformTrait overrides base class method
-func (t *containerTrait) IsPlatformTrait() bool {
- return true
-}
-
-func (t *containerTrait) configureService(e *Environment) {
+func (t *containerTrait) configureService(e *Environment, container *corev1.Container) {
service := e.Resources.GetServiceForIntegration(e.Integration)
if service == nil {
return
}
- container := e.Resources.GetContainerByName(t.Name)
- if container == nil {
- return
- }
-
containerPort := corev1.ContainerPort{
Name: t.PortName,
ContainerPort: int32(t.Port),
@@ -271,3 +390,82 @@ func (t *containerTrait) configureResources(_ *Environment, container *corev1.Co
}
}
}
+func (t *containerTrait) configureProbes(e *Environment, container *corev1.Container, port int, path string) error {
+ if !t.ProbesEnabled {
+ return nil
+ }
+
+ if e.ApplicationProperties == nil {
+ e.ApplicationProperties = make(map[string]string)
+ }
+
+ switch e.CamelCatalog.Runtime.Provider {
+ case v1.RuntimeProviderMain:
+ e.ApplicationProperties["customizer.inspector.enabled"] = True
+ e.ApplicationProperties["customizer.inspector.bind-host"] = "0.0.0.0"
+ e.ApplicationProperties["customizer.inspector.bind-port"] = strconv.Itoa(port)
+ e.ApplicationProperties["customizer.health.enabled"] = True
+ e.ApplicationProperties["customizer.health.path"] = path
+ case v1.RuntimeProviderQuarkus:
+ // Quarkus does not offer a runtime option to change the path of the health endpoint but there
+ // is a build time property:
+ //
+ // quarkus.smallrye-health.root-path
+ //
+ // so failing in case user tries to change the path.
+ //
+ // NOTE: we could probably be more opinionated and make the path an internal detail.
+ if path != defaultProbePath {
+ return fmt.Errorf("health check root path can't be changed at runtimme on Quarkus")
+ }
+ default:
+ return fmt.Errorf("unsupported runtime: %s", e.CamelCatalog.Runtime.Provider)
+ }
+
+ container.LivenessProbe = t.newLivenessProbe(port, path)
+ container.ReadinessProbe = t.newReadinessProbe(port, path)
+
+ return nil
+}
+
+func (t *containerTrait) newLivenessProbe(port int, path string) *corev1.Probe {
+ action := corev1.HTTPGetAction{}
+ action.Path = path
+
+ 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,
+ },
+ },
+ }
+
+ 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
new file mode 100644
index 0000000..930710b
--- /dev/null
+++ b/pkg/trait/container_probes_test.go
@@ -0,0 +1,190 @@
+/*
+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 (
+ "testing"
+
+ serving "knative.dev/serving/pkg/apis/serving/v1"
+
+ "github.com/apache/camel-k/pkg/util/camel"
+ "github.com/apache/camel-k/pkg/util/kubernetes"
+ appsv1 "k8s.io/api/apps/v1"
+
+ v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func newTestProbesEnv(t *testing.T, provider v1.RuntimeProvider) Environment {
+ var catalog *camel.RuntimeCatalog = nil
+ var err error = nil
+
+ switch provider {
+ case v1.RuntimeProviderMain:
+ catalog, err = camel.DefaultCatalog()
+ case v1.RuntimeProviderQuarkus:
+ catalog, err = camel.QuarkusCatalog()
+ }
+
+ assert.Nil(t, err)
+ assert.NotNil(t, catalog)
+
+ return Environment{
+ CamelCatalog: catalog,
+ Integration: &v1.Integration{
+ Status: v1.IntegrationStatus{},
+ },
+ Resources: kubernetes.NewCollection(),
+ ApplicationProperties: make(map[string]string),
+ }
+}
+
+func newTestContainerTrait() *containerTrait {
+ enabled := true
+
+ tr := newContainerTrait().(*containerTrait)
+ tr.ProbesEnabled = enabled
+
+ return tr
+}
+
+func TestProbesDeps(t *testing.T) {
+ env := newTestProbesEnv(t, v1.RuntimeProviderMain)
+ env.Integration.Status.Phase = v1.IntegrationPhaseInitialization
+
+ ctr := newTestContainerTrait()
+
+ ok, err := ctr.Configure(&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.k/camel-k-runtime-health")
+}
+
+func TestProbesDepsQuarkus(t *testing.T) {
+ env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+ env.Integration.Status.Phase = v1.IntegrationPhaseInitialization
+
+ ctr := newTestContainerTrait()
+ ctr.ProbePort = 9191
+
+ ok, err := ctr.Configure(&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{}
+
+ env := newTestProbesEnv(t, v1.RuntimeProviderMain)
+ env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+ env.Resources.Add(&target)
+
+ ctr := newTestContainerTrait()
+ ctr.ProbePort = 9191
+ ctr.LivenessTimeout = 1234
+
+ err := ctr.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, "", 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, int32(1234), target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
+}
+
+func TestProbesOnDeploymentWithNoHttpPort(t *testing.T) {
+ target := appsv1.Deployment{}
+
+ env := newTestProbesEnv(t, v1.RuntimeProviderMain)
+ env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+ env.Resources.Add(&target)
+
+ ctr := newTestContainerTrait()
+ ctr.PortName = "custom"
+ ctr.ProbePort = 9191
+ ctr.LivenessTimeout = 1234
+
+ err := ctr.Apply(&env)
+ assert.Nil(t, err)
+
+ assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
+ assert.Equal(t, int32(9191), 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(9191), 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 TestProbesOnKnativeService(t *testing.T) {
+ target := serving.Service{}
+
+ env := newTestProbesEnv(t, v1.RuntimeProviderMain)
+ env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+ env.Resources.Add(&target)
+
+ ctr := newTestContainerTrait()
+ ctr.ProbePort = 9191
+ ctr.LivenessTimeout = 1234
+
+ err := ctr.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{}
+
+ env := newTestProbesEnv(t, v1.RuntimeProviderMain)
+ env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+ env.Resources.Add(&target)
+
+ ctr := newTestContainerTrait()
+ ctr.PortName = "custom"
+ ctr.ProbePort = 9191
+ ctr.LivenessTimeout = 1234
+
+ err := ctr.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)
+}
diff --git a/pkg/trait/probes.go b/pkg/trait/probes.go
deleted file mode 100644
index 6049b1f..0000000
--- a/pkg/trait/probes.go
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-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 (
- "fmt"
- "sort"
- "strconv"
-
- v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
- "github.com/apache/camel-k/pkg/util"
- "k8s.io/apimachinery/pkg/util/intstr"
-
- appsv1 "k8s.io/api/apps/v1"
- corev1 "k8s.io/api/core/v1"
-)
-
-// The Probes trait allows to configure Liveness and Readiness probes on the integration container.
-//
-// +camel-k:trait=probes
-type probesTrait struct {
- BaseTrait `property:",squash"`
- // Configures the host on which the probe is exposed (default `0.0.0.0`).
- BindHost string `property:"bind-host"`
- // Configures the port on which the probe is exposed (default `8080`).
- BindPort int `property:"bind-port"`
- // Path to access on the probe ( default `/health`).
- Path string `property:"path"`
- // Number of seconds after the container has started before liveness probes are initiated.
- LivenessInitialDelay int32 `property:"liveness-initial-delay"`
- // Number of seconds after which the probe times out. Applies to the liveness probe.
- LivenessTimeout int32 `property:"liveness-timeout"`
- // How often to perform the probe. Applies to the liveness probe.
- LivenessPeriod int32 `property:"liveness-period"`
- // Minimum consecutive successes for the probe to be considered successful after having failed. Applies to the liveness probe.
- LivenessSuccessThreshold int32 `property:"liveness-success-threshold"`
- // Minimum consecutive failures for the probe to be considered failed after having succeeded. Applies to the liveness probe.
- LivenessFailureThreshold int32 `property:"liveness-failure-threshold"`
- // Number of seconds after the container has started before readiness probes are initiated.
- ReadinessInitialDelay int32 `property:"readiness-initial-delay"`
- // Number of seconds after which the probe times out. Applies to the readiness probe.
- ReadinessTimeout int32 `property:"readiness-timeout"`
- // How often to perform the probe. Applies to the readiness probe.
- ReadinessPeriod int32 `property:"readiness-period"`
- // Minimum consecutive successes for the probe to be considered successful after having failed. Applies to the readiness probe.
- ReadinessSuccessThreshold int32 `property:"readiness-success-threshold"`
- // Minimum consecutive failures for the probe to be considered failed after having succeeded. Applies to the readiness probe.
- ReadinessFailureThreshold int32 `property:"readiness-failure-threshold"`
-}
-
-func newProbesTrait() Trait {
- return &probesTrait{
- BaseTrait: NewBaseTrait("probes", 2100),
- BindHost: "0.0.0.0",
- BindPort: 8081,
- Path: "/health",
- }
-}
-
-func (t *probesTrait) Configure(e *Environment) (bool, error) {
- if t.Enabled != nil && *t.Enabled {
- // check if the runtime provides 'health' capabilities
- if _, ok := e.CamelCatalog.Runtime.Capabilities["health"]; !ok {
- t.L.Infof("the runtime provider %s does not declare 'health' capability", e.CamelCatalog.Runtime.Provider)
- }
-
- return e.IntegrationInPhase(
- v1.IntegrationPhaseInitialization,
- v1.IntegrationPhaseDeploying,
- v1.IntegrationPhaseRunning,
- ), nil
- }
-
- return false, nil
-}
-
-func (t *probesTrait) Apply(e *Environment) error {
- t.computeDependencies(e)
-
- if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
- e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
- v1.ConfigurationSpec{Type: "property", Value: "customizer.inspector.enabled=true"},
- v1.ConfigurationSpec{Type: "property", Value: "customizer.inspector.bind-host=" + t.BindHost},
- v1.ConfigurationSpec{Type: "property", Value: "customizer.inspector.bind-port=" + strconv.Itoa(t.BindPort)},
- v1.ConfigurationSpec{Type: "property", Value: "customizer.health.enabled=true"},
- v1.ConfigurationSpec{Type: "property", Value: "customizer.health.path=" + t.Path},
- )
- }
-
- if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
- e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
- if len(deployment.Spec.Template.Spec.Containers) != 1 {
- return
- }
-
- deployment.Spec.Template.Spec.Containers[0].LivenessProbe = t.newLivenessProbe()
- deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = t.newReadinessProbe()
- })
- }
-
- return nil
-}
-
-func (t *probesTrait) newLivenessProbe() *corev1.Probe {
- p := corev1.Probe{
- Handler: corev1.Handler{
- HTTPGet: &corev1.HTTPGetAction{
- Port: intstr.FromInt(t.BindPort),
- Path: t.Path,
- },
- },
- }
-
- p.InitialDelaySeconds = t.LivenessInitialDelay
- p.TimeoutSeconds = t.LivenessTimeout
- p.PeriodSeconds = t.LivenessPeriod
- p.SuccessThreshold = t.LivenessSuccessThreshold
- p.FailureThreshold = t.LivenessFailureThreshold
-
- return &p
-}
-
-func (t *probesTrait) newReadinessProbe() *corev1.Probe {
- p := corev1.Probe{
- Handler: corev1.Handler{
- HTTPGet: &corev1.HTTPGetAction{
- Port: intstr.FromInt(t.BindPort),
- Path: t.Path,
- },
- },
- }
-
- p.InitialDelaySeconds = t.ReadinessInitialDelay
- p.TimeoutSeconds = t.ReadinessTimeout
- p.PeriodSeconds = t.ReadinessPeriod
- p.SuccessThreshold = t.ReadinessSuccessThreshold
- p.FailureThreshold = t.ReadinessFailureThreshold
-
- return &p
-}
-
-func (t *probesTrait) computeDependencies(e *Environment) {
- if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
- return
- }
-
- if capability, ok := e.CamelCatalog.Runtime.Capabilities["health"]; ok {
- for _, dependency := range capability.Dependencies {
- util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fmt.Sprintf("mvn:%s/%s", dependency.GroupID, dependency.ArtifactID))
- }
-
- // sort the dependencies to get always the same list if they don't change
- sort.Strings(e.Integration.Status.Dependencies)
- }
-}
diff --git a/pkg/trait/probes_test.go b/pkg/trait/probes_test.go
deleted file mode 100644
index 6d4c046..0000000
--- a/pkg/trait/probes_test.go
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-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 (
- "testing"
-
- "github.com/apache/camel-k/pkg/util/camel"
-
- v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
- "github.com/apache/camel-k/pkg/util/kubernetes"
-
- "github.com/stretchr/testify/assert"
-
- appsv1 "k8s.io/api/apps/v1"
- corev1 "k8s.io/api/core/v1"
- serving "knative.dev/serving/pkg/apis/serving/v1"
-)
-
-func TestProbesDeps(t *testing.T) {
- catalog, err := camel.DefaultCatalog()
- assert.Nil(t, err)
-
- e := Environment{
- CamelCatalog: catalog,
- Integration: &v1.Integration{
- Status: v1.IntegrationStatus{
- Phase: v1.IntegrationPhaseInitialization,
- },
- },
- }
-
- enabled := true
-
- tr := newProbesTrait().(*probesTrait)
- tr.Enabled = &enabled
- tr.BindPort = 9191
-
- ok, err := tr.Configure(&e)
- assert.Nil(t, err)
- assert.True(t, ok)
-
- err = tr.Apply(&e)
- assert.Nil(t, err)
- assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel.k/camel-k-runtime-health")
-}
-
-func TestProbesDepsQuarkus(t *testing.T) {
- catalog, err := camel.QuarkusCatalog()
- assert.Nil(t, err)
-
- e := Environment{
- CamelCatalog: catalog,
- Integration: &v1.Integration{
- Status: v1.IntegrationStatus{
- Phase: v1.IntegrationPhaseInitialization,
- },
- },
- }
-
- enabled := true
-
- tr := newProbesTrait().(*probesTrait)
- tr.Enabled = &enabled
- tr.BindPort = 9191
-
- ok, err := tr.Configure(&e)
- assert.Nil(t, err)
- assert.True(t, ok)
-
- err = tr.Apply(&e)
- assert.Nil(t, err)
- assert.Contains(t, e.Integration.Status.Dependencies, "mvn:org.apache.camel.quarkus/camel-quarkus-microprofile-health")
-}
-
-func TestProbesOnDeployment(t *testing.T) {
- catalog, err := camel.DefaultCatalog()
- assert.Nil(t, err)
-
- target := appsv1.Deployment{
- Spec: appsv1.DeploymentSpec{
- Template: corev1.PodTemplateSpec{
- Spec: corev1.PodSpec{
- Containers: []corev1.Container{
- {},
- },
- },
- },
- },
- }
-
- e := Environment{
- CamelCatalog: catalog,
- Resources: kubernetes.NewCollection(&target),
- Integration: &v1.Integration{
- Status: v1.IntegrationStatus{
- Phase: v1.IntegrationPhaseDeploying,
- },
- },
- }
-
- enabled := true
-
- tr := newProbesTrait().(*probesTrait)
- tr.Enabled = &enabled
- tr.BindPort = 9191
- tr.LivenessTimeout = 1234
-
- ok, err := tr.Configure(&e)
- assert.Nil(t, err)
- assert.True(t, ok)
-
- err = tr.Apply(&e)
- assert.Nil(t, err)
- assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
- assert.Equal(t, int32(9191), target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
- assert.Equal(t, "/health", 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(9191), target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
- assert.Equal(t, "/health", target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
- assert.Equal(t, int32(1234), target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
-}
-
-func TestProbesOnKnativeService(t *testing.T) {
- catalog, err := camel.DefaultCatalog()
- assert.Nil(t, err)
-
- target := serving.Service{
- Spec: serving.ServiceSpec{
- ConfigurationSpec: serving.ConfigurationSpec{
- Template: serving.RevisionTemplateSpec{
- Spec: serving.RevisionSpec{
- PodSpec: corev1.PodSpec{
- Containers: []corev1.Container{
- {
- Image: "dummy",
- },
- },
- },
- },
- },
- },
- },
- }
-
- e := Environment{
- CamelCatalog: catalog,
- Resources: kubernetes.NewCollection(&target),
- Integration: &v1.Integration{
- Status: v1.IntegrationStatus{
- Phase: v1.IntegrationPhaseDeploying,
- },
- },
- }
-
- enabled := true
-
- tr := newProbesTrait().(*probesTrait)
- tr.Enabled = &enabled
- tr.BindPort = 9191
- tr.ReadinessTimeout = 4321
-
- ok, err := tr.Configure(&e)
- assert.Nil(t, err)
- assert.True(t, ok)
-
- err = tr.Apply(&e)
- assert.Nil(t, err)
- assert.Nil(t, target.Spec.ConfigurationSpec.Template.Spec.Containers[0].LivenessProbe)
- assert.Nil(t, target.Spec.ConfigurationSpec.Template.Spec.Containers[0].ReadinessProbe)
-}
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index 27ea26d..265cfa9 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -40,7 +40,6 @@ func init() {
AddToTraits(newJolokiaTrait)
AddToTraits(newPrometheusTrait)
AddToTraits(newJvmTrait)
- AddToTraits(newProbesTrait)
AddToTraits(newRouteTrait)
AddToTraits(newIstioTrait)
AddToTraits(newIngressTrait)
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index e6d751e..61ab07d 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -336,11 +336,8 @@ func (e *Environment) DetermineNamespace() string {
return ""
}
-// ComputeConfigMaps --
-func (e *Environment) ComputeConfigMaps() []runtime.Object {
- sources := e.Integration.Sources()
- maps := make([]runtime.Object, 0, len(sources)+1)
-
+// ComputeApplicationProperties --
+func (e *Environment) ComputeApplicationProperties() *corev1.ConfigMap {
// application properties
applicationProperties := ""
@@ -349,28 +346,33 @@ func (e *Environment) ComputeConfigMaps() []runtime.Object {
}
if applicationProperties != "" {
- maps = append(
- maps,
- &corev1.ConfigMap{
- TypeMeta: metav1.TypeMeta{
- Kind: "ConfigMap",
- APIVersion: "v1",
- },
- ObjectMeta: metav1.ObjectMeta{
- Name: e.Integration.Name + "-application-properties",
- Namespace: e.Integration.Namespace,
- Labels: map[string]string{
- "camel.apache.org/integration": e.Integration.Name,
- "camel.apache.org/properties.type": "application",
- },
- },
- Data: map[string]string{
- "application.properties": applicationProperties,
+ return &corev1.ConfigMap{
+ TypeMeta: metav1.TypeMeta{
+ Kind: "ConfigMap",
+ APIVersion: "v1",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: e.Integration.Name + "-application-properties",
+ Namespace: e.Integration.Namespace,
+ Labels: map[string]string{
+ "camel.apache.org/integration": e.Integration.Name,
+ "camel.apache.org/properties.type": "application",
},
},
- )
+ Data: map[string]string{
+ "application.properties": applicationProperties,
+ },
+ }
}
+ return nil
+}
+
+// ComputeConfigMaps --
+func (e *Environment) ComputeConfigMaps() []runtime.Object {
+ sources := e.Integration.Sources()
+ maps := make([]runtime.Object, 0, len(sources)+1)
+
// combine properties of integration with kit, integration
// properties have the priority
userProperties := ""
diff --git a/pkg/util/kubernetes/collection.go b/pkg/util/kubernetes/collection.go
index dd660c5..d4b6140 100644
--- a/pkg/util/kubernetes/collection.go
+++ b/pkg/util/kubernetes/collection.go
@@ -76,7 +76,9 @@ func (c *Collection) AsKubernetesList() *corev1.List {
// Add adds a resource to the collection
func (c *Collection) Add(resource runtime.Object) {
- c.items = append(c.items, resource)
+ if resource != nil {
+ c.items = append(c.items, resource)
+ }
}
// AddAll adds all resources to the collection
@@ -93,6 +95,17 @@ func (c *Collection) VisitDeployment(visitor func(*appsv1.Deployment)) {
})
}
+// VisitDeploymentE executes the visitor function on all Deployment resources
+func (c *Collection) VisitDeploymentE(visitor func(*appsv1.Deployment) error) error {
+ return c.VisitE(func(res runtime.Object) error {
+ if conv, ok := res.(*appsv1.Deployment); ok {
+ return visitor(conv)
+ }
+
+ return nil
+ })
+}
+
// GetDeployment returns a Deployment that matches the given function
func (c *Collection) GetDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment {
var retValue *appsv1.Deployment
@@ -250,6 +263,17 @@ func (c *Collection) VisitCronJob(visitor func(*v1beta1.CronJob)) {
})
}
+// VisitCronJobE executes the visitor function on all CronJob resources
+func (c *Collection) VisitCronJobE(visitor func(*v1beta1.CronJob) error) error {
+ return c.VisitE(func(res runtime.Object) error {
+ if conv, ok := res.(*v1beta1.CronJob); ok {
+ return visitor(conv)
+ }
+
+ return nil
+ })
+}
+
// VisitKnativeService executes the visitor function on all Knative serving Service resources
func (c *Collection) VisitKnativeService(visitor func(*serving.Service)) {
c.Visit(func(res runtime.Object) {
@@ -259,6 +283,17 @@ func (c *Collection) VisitKnativeService(visitor func(*serving.Service)) {
})
}
+// VisitKnativeServiceE executes the visitor function on all Knative serving Service resources
+func (c *Collection) VisitKnativeServiceE(visitor func(*serving.Service) error) error {
+ return c.VisitE(func(res runtime.Object) error {
+ if conv, ok := res.(*serving.Service); ok {
+ return visitor(conv)
+ }
+
+ return nil
+ })
+}
+
// VisitKnativeTrigger executes the visitor function on all Knative eventing Trigger resources
func (c *Collection) VisitKnativeTrigger(visitor func(trigger *eventing.Trigger)) {
c.Visit(func(res runtime.Object) {
@@ -358,6 +393,18 @@ func (c *Collection) Visit(visitor func(runtime.Object)) {
}
}
+// VisitE executes the visitor function on all resources breaking if the visitor function
+// returns an error
+func (c *Collection) VisitE(visitor func(runtime.Object) error) error {
+ for _, res := range c.items {
+ if err := visitor(res); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
// Remove removes the given element from the collection and returns it
func (c *Collection) Remove(selector func(runtime.Object) bool) runtime.Object {
for idx, res := range c.items {
@@ -369,6 +416,7 @@ func (c *Collection) Remove(selector func(runtime.Object) bool) runtime.Object {
return nil
}
+// VisitServiceMonitor ---
func (c *Collection) VisitServiceMonitor(visitor func(*monitoringv1.ServiceMonitor)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*monitoringv1.ServiceMonitor); ok {
@@ -377,6 +425,7 @@ func (c *Collection) VisitServiceMonitor(visitor func(*monitoringv1.ServiceMonit
})
}
+// GetServiceMonitor ---
func (c *Collection) GetServiceMonitor(filter func(*monitoringv1.ServiceMonitor) bool) *monitoringv1.ServiceMonitor {
var retValue *monitoringv1.ServiceMonitor
c.VisitServiceMonitor(func(serviceMonitor *monitoringv1.ServiceMonitor) {