From dab0bce01d6a28ec6070303502c371640f56ea54 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Thu, 16 Jan 2020 10:33:20 +0100 Subject: [PATCH 01/13] chore(trait): Remove environment classpath member --- pkg/trait/builder_test.go | 2 -- pkg/trait/classpath.go | 16 ++++----- pkg/trait/classpath_test.go | 60 ++++--------------------------- pkg/trait/container_test.go | 3 -- pkg/trait/environment_test.go | 4 --- pkg/trait/knative_service_test.go | 3 -- pkg/trait/knative_test.go | 3 -- pkg/trait/route_test.go | 2 -- pkg/trait/service_test.go | 4 --- pkg/trait/trait_test.go | 2 -- pkg/trait/trait_types.go | 14 -------- 11 files changed, 13 insertions(+), 100 deletions(-) diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go index 591c8a06cb..22e7849062 100644 --- a/pkg/trait/builder_test.go +++ b/pkg/trait/builder_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" @@ -159,7 +158,6 @@ func createBuilderTestEnv(cluster v1.IntegrationPlatformCluster, strategy v1.Int EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } res.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index aedbf9192b..6cf1c629db 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -75,19 +75,17 @@ func (t *classpathTrait) Apply(e *Environment) error { return fmt.Errorf("unable to find integration kit %s", e.Integration.Status.Kit) } - if e.Classpath == nil { - e.Classpath = strset.New() - } + classpath := strset.New() - e.Classpath.Add("/etc/camel/resources") - e.Classpath.Add("./resources") + classpath.Add("/etc/camel/resources") + classpath.Add("./resources") quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait) if quarkus.isEnabled() { quarkus.addClasspath(e) } else { for _, artifact := range kit.Status.Artifacts { - e.Classpath.Add(artifact.Target) + classpath.Add(artifact.Target) } } @@ -97,7 +95,7 @@ func (t *classpathTrait) Apply(e *Environment) error { // the classpath so we assume the all jars in /deployments/dependencies/ have // to be taken into account // - e.Classpath.Add("/deployments/dependencies/*") + classpath.Add("/deployments/dependencies/*") } containerName := defaultContainerName @@ -109,10 +107,10 @@ func (t *classpathTrait) Apply(e *Environment) error { container := e.Resources.GetContainerByName(containerName) if container != nil { for _, m := range container.VolumeMounts { - e.Classpath.Add(m.MountPath) + classpath.Add(m.MountPath) } - items := e.Classpath.List() + items := classpath.List() // keep classpath sorted sort.Strings(items) diff --git a/pkg/trait/classpath_test.go b/pkg/trait/classpath_test.go index 3c4c221b95..1cb50ad889 100644 --- a/pkg/trait/classpath_test.go +++ b/pkg/trait/classpath_test.go @@ -71,41 +71,6 @@ func TestConfigureClasspathDisabledTraitDoesNotSucceed(t *testing.T) { assert.False(t, configured) } -func TestApplyClasspathTraitPlaftormIntegrationKitLazyInstantiation(t *testing.T) { - trait, environment := createNominalClasspathTest() - environment.IntegrationKit = nil - environment.Integration.Namespace = "kit-namespace" - environment.Integration.Status.Kit = "kit-name" - - err := trait.Apply(environment) - - assert.Nil(t, err) - assert.Equal(t, strset.New("/etc/camel/resources", "./resources"), environment.Classpath) -} - -func TestApplyClasspathTraitExternalIntegrationKitLazyInstantiation(t *testing.T) { - trait, environment := createClasspathTestWithKitType(v1.IntegrationKitTypeExternal) - environment.IntegrationKit = nil - environment.Integration.Namespace = "kit-namespace" - environment.Integration.Status.Kit = "kit-name" - - err := trait.Apply(environment) - - assert.Nil(t, err) - assert.Equal(t, strset.New("/etc/camel/resources", "./resources", "/deployments/dependencies/*"), environment.Classpath) -} - -func TestApplyClasspathTraitWithIntegrationKitStatusArtifact(t *testing.T) { - trait, environment := createNominalClasspathTest() - environment.IntegrationKit.Status.Artifacts = []v1.Artifact{{ID: "", Location: "", Target: "/dep/target"}} - - err := trait.Apply(environment) - - assert.Nil(t, err) - assert.NotNil(t, environment.Classpath) - assert.Equal(t, strset.New("/etc/camel/resources", "./resources", "/dep/target"), environment.Classpath) -} - func TestApplyClasspathTraitWithDeploymentResource(t *testing.T) { trait, environment := createNominalClasspathTest() @@ -132,12 +97,11 @@ func TestApplyClasspathTraitWithDeploymentResource(t *testing.T) { err := trait.Apply(environment) - cp := environment.Classpath.List() + assert.Nil(t, err) + + cp := strset.New("/etc/camel/resources", "./resources", "/mount/path").List() sort.Strings(cp) - assert.Nil(t, err) - assert.NotNil(t, environment.Classpath) - assert.Equal(t, strset.New("/etc/camel/resources", "./resources", "/mount/path"), environment.Classpath) assert.Len(t, d.Spec.Template.Spec.Containers[0].Env, 1) assert.Equal(t, "JAVA_CLASSPATH", d.Spec.Template.Spec.Containers[0].Env[0].Name) assert.Equal(t, strings.Join(cp, ":"), d.Spec.Template.Spec.Containers[0].Env[0].Value) @@ -163,33 +127,21 @@ func TestApplyClasspathTraitWithKNativeResource(t *testing.T) { err := trait.Apply(environment) - cp := environment.Classpath.List() + assert.Nil(t, err) + + cp := strset.New("/etc/camel/resources", "./resources", "/mount/path").List() sort.Strings(cp) - assert.Nil(t, err) - assert.NotNil(t, environment.Classpath) - assert.ElementsMatch(t, []string{"/etc/camel/resources", "./resources", "/mount/path"}, cp) assert.Len(t, s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env, 1) assert.Equal(t, "JAVA_CLASSPATH", s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env[0].Name) assert.Equal(t, strings.Join(cp, ":"), s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env[0].Value) } -func TestApplyClasspathTraitWithNominalIntegrationKit(t *testing.T) { - trait, environment := createNominalClasspathTest() - - err := trait.Apply(environment) - - assert.Nil(t, err) - assert.NotNil(t, environment.Classpath) - assert.Equal(t, strset.New("/etc/camel/resources", "./resources"), environment.Classpath) -} - func createNominalClasspathTest() (*classpathTrait, *Environment) { return createClasspathTestWithKitType(v1.IntegrationKitTypePlatform) } func createClasspathTestWithKitType(kitType string) (*classpathTrait, *Environment) { - client, _ := test.NewFakeClient( &v1.IntegrationKit{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go index 26c20c5342..8510fa6c58 100644 --- a/pkg/trait/container_test.go +++ b/pkg/trait/container_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" @@ -70,7 +69,6 @@ func TestContainerWithDefaults(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() @@ -133,7 +131,6 @@ func TestContainerWithCustomName(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/environment_test.go b/pkg/trait/environment_test.go index 2e1993781e..fbcbfc94f5 100644 --- a/pkg/trait/environment_test.go +++ b/pkg/trait/environment_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" @@ -64,7 +63,6 @@ func TestDefaultEnvironment(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } env.Platform.ResyncStatusFullConfig() @@ -133,7 +131,6 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } env.Platform.ResyncStatusFullConfig() @@ -202,7 +199,6 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } env.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go index 6a312ce169..cd16d2f332 100644 --- a/pkg/trait/knative_service_test.go +++ b/pkg/trait/knative_service_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" @@ -110,7 +109,6 @@ func TestKnativeService(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() @@ -237,7 +235,6 @@ func TestKnativeServiceWithCustomContainerName(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/knative_test.go b/pkg/trait/knative_test.go index c60271f7f3..fc119c5312 100644 --- a/pkg/trait/knative_test.go +++ b/pkg/trait/knative_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" @@ -96,7 +95,6 @@ func TestKnativeEnvConfigurationFromTrait(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: k8sutils.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() @@ -206,7 +204,6 @@ func TestKnativeEnvConfigurationFromSource(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: k8sutils.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/route_test.go b/pkg/trait/route_test.go index 87c0068fa3..bba96d27ba 100644 --- a/pkg/trait/route_test.go +++ b/pkg/trait/route_test.go @@ -22,7 +22,6 @@ import ( "testing" "github.com/rs/xid" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" routev1 "github.com/openshift/api/route/v1" @@ -68,7 +67,6 @@ func createTestRouteEnvironment(t *testing.T, name string) *Environment { }, EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), - Classpath: strset.New(), Resources: kubernetes.NewCollection( &corev1.Service{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go index f5e6d9f417..49a525e4d1 100644 --- a/pkg/trait/service_test.go +++ b/pkg/trait/service_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" @@ -94,7 +93,6 @@ func TestServiceWithDefaults(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() @@ -193,7 +191,6 @@ func TestService(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() @@ -277,7 +274,6 @@ func TestServiceWithCustomContainerName(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } environment.Platform.ResyncStatusFullConfig() diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go index 0738777a15..bab4131e7e 100644 --- a/pkg/trait/trait_test.go +++ b/pkg/trait/trait_test.go @@ -21,7 +21,6 @@ import ( "context" "testing" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" routev1 "github.com/openshift/api/route/v1" @@ -470,7 +469,6 @@ func createTestEnv(t *testing.T, cluster v1.IntegrationPlatformCluster, script s EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), - Classpath: strset.New(), } res.Platform.ResyncStatusFullConfig() return res diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index 0305b13179..de8a6c9c94 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -25,8 +25,6 @@ import ( "strconv" "strings" - "github.com/scylladb/go-set/strset" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" controller "sigs.k8s.io/controller-runtime/pkg/client" @@ -155,7 +153,6 @@ type Environment struct { ConfiguredTraits []Trait ExecutedTraits []Trait EnvVars []corev1.EnvVar - Classpath *strset.Set } // ControllerStrategy is used to determine the kind of controller that needs to be created for the integration @@ -181,17 +178,6 @@ func (e *Environment) GetTrait(id ID) Trait { return nil } -// GetConfiguredTrait -- -func (e *Environment) GetConfiguredTrait(id ID) Trait { - for _, t := range e.ConfiguredTraits { - if t.ID() == id { - return t - } - } - - return nil -} - // IntegrationInPhase -- func (e *Environment) IntegrationInPhase(phases ...v1.IntegrationPhase) bool { if e.Integration == nil { From 70a7d5acf0e561b3af93a413428f073a11feed5a Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 09:23:31 +0100 Subject: [PATCH 02/13] chore(trait): Configure classpath using container args --- pkg/trait/classpath.go | 7 +------ pkg/trait/knative_service_test.go | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index 6cf1c629db..5281477500 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -28,7 +28,6 @@ import ( k8sclient "sigs.k8s.io/controller-runtime/pkg/client" v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/envvar" ) // The Classpath trait is used internally to configure the classpath of the final integration. @@ -90,11 +89,9 @@ func (t *classpathTrait) Apply(e *Environment) error { } if kit.Labels["camel.apache.org/kit.type"] == v1.IntegrationKitTypeExternal { - // // In case of an external created kit, we do not have any information about // the classpath so we assume the all jars in /deployments/dependencies/ have // to be taken into account - // classpath.Add("/deployments/dependencies/*") } @@ -109,13 +106,11 @@ func (t *classpathTrait) Apply(e *Environment) error { for _, m := range container.VolumeMounts { classpath.Add(m.MountPath) } - items := classpath.List() - // keep classpath sorted sort.Strings(items) - envvar.SetVal(&container.Env, "JAVA_CLASSPATH", strings.Join(items, ":")) + container.Args = append(container.Args, "-cp", strings.Join(items, ":")) } return nil diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go index cd16d2f332..92675bed6e 100644 --- a/pkg/trait/knative_service_test.go +++ b/pkg/trait/knative_service_test.go @@ -172,7 +172,6 @@ func TestKnativeService(t *testing.T) { } }) - test.EnvVarExists(t, spec.Containers[0].Env, "JAVA_CLASSPATH") test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_ROUTES", "file:/etc/camel/sources/i-source-000/routes.js?language=js&compression=true") test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties") test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d") From c4d23bd7145e4caad15adeed4c71b205c7eb8b74 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 15:33:06 +0100 Subject: [PATCH 03/13] chore(trait): Default integration container command to 'java' --- pkg/trait/container.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/trait/container.go b/pkg/trait/container.go index 0a3cfa6ce6..02dd117d1a 100644 --- a/pkg/trait/container.go +++ b/pkg/trait/container.go @@ -21,14 +21,16 @@ import ( "fmt" "strings" - v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/envvar" appsv1 "k8s.io/api/apps/v1" "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" + serving "knative.dev/serving/pkg/apis/serving/v1" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/util/envvar" ) const ( @@ -99,9 +101,10 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) { func (t *containerTrait) Apply(e *Environment) error { container := corev1.Container{ - Name: t.Name, - Image: e.Integration.Status.Image, - Env: make([]corev1.EnvVar, 0), + Name: t.Name, + Image: e.Integration.Status.Image, + Env: make([]corev1.EnvVar, 0), + Command: []string{"java"}, } // combine Environment of integration with platform, kit, integration From 64c5cd78112ad0d5c7e6291c6b2d3416af5edaf4 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 16:22:12 +0100 Subject: [PATCH 04/13] chore(trait): Add main class or JAR to integration container arguments --- pkg/trait/classpath.go | 12 ++++++++++++ pkg/trait/classpath_test.go | 17 ++++++++++------- pkg/trait/environment.go | 12 +----------- pkg/trait/quarkus.go | 5 ----- pkg/trait/quarkus_test.go | 9 --------- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index 5281477500..bbbe845836 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -28,6 +28,11 @@ import ( k8sclient "sigs.k8s.io/controller-runtime/pkg/client" v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/util/defaults" +) + +const ( + defaultMainClass = "org.apache.camel.k.main.Application" ) // The Classpath trait is used internally to configure the classpath of the final integration. @@ -111,6 +116,13 @@ func (t *classpathTrait) Apply(e *Environment) error { sort.Strings(items) container.Args = append(container.Args, "-cp", strings.Join(items, ":")) + + quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait) + if quarkus.isEnabled() { + container.Args = append(container.Args, "-jar", "camel-k-integration-"+defaults.Version+"-runner.jar") + } else { + container.Args = append(container.Args, defaultMainClass) + } } return nil diff --git a/pkg/trait/classpath_test.go b/pkg/trait/classpath_test.go index 1cb50ad889..5b12675f07 100644 --- a/pkg/trait/classpath_test.go +++ b/pkg/trait/classpath_test.go @@ -20,7 +20,6 @@ package trait import ( "context" "sort" - "strings" "testing" appsv1 "k8s.io/api/apps/v1" @@ -102,9 +101,11 @@ func TestApplyClasspathTraitWithDeploymentResource(t *testing.T) { cp := strset.New("/etc/camel/resources", "./resources", "/mount/path").List() sort.Strings(cp) - assert.Len(t, d.Spec.Template.Spec.Containers[0].Env, 1) - assert.Equal(t, "JAVA_CLASSPATH", d.Spec.Template.Spec.Containers[0].Env[0].Name) - assert.Equal(t, strings.Join(cp, ":"), d.Spec.Template.Spec.Containers[0].Env[0].Value) + assert.Equal(t, d.Spec.Template.Spec.Containers[0].Args, []string{ + "-cp", + "./resources:/etc/camel/resources:/mount/path", + "org.apache.camel.k.main.Application", + }) } func TestApplyClasspathTraitWithKNativeResource(t *testing.T) { @@ -132,9 +133,11 @@ func TestApplyClasspathTraitWithKNativeResource(t *testing.T) { cp := strset.New("/etc/camel/resources", "./resources", "/mount/path").List() sort.Strings(cp) - assert.Len(t, s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env, 1) - assert.Equal(t, "JAVA_CLASSPATH", s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env[0].Name) - assert.Equal(t, strings.Join(cp, ":"), s.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env[0].Value) + assert.Equal(t, s.Spec.Template.Spec.Containers[0].Args, []string{ + "-cp", + "./resources:/etc/camel/resources:/mount/path", + "org.apache.camel.k.main.Application", + }) } func createNominalClasspathTest() (*classpathTrait, *Environment) { diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go index 7621220562..b9d095eaac 100644 --- a/pkg/trait/environment.go +++ b/pkg/trait/environment.go @@ -24,7 +24,7 @@ import ( ) // The environment trait is used internally to inject standard environment variables in the integration container, -// such as `NAMESPACE`, `POD_NAME`, `JAVA_MAIN_CLASS` and others. +// such as `NAMESPACE`, `POD_NAME` and others. // // +camel-k:trait=environment type environmentTrait struct { @@ -38,9 +38,6 @@ const ( envVarCamelKVersion = "CAMEL_K_VERSION" envVarCamelKRuntimeVersion = "CAMEL_K_RUNTIME_VERSION" envVarCamelVersion = "CAMEL_VERSION" - envVarMainClass = "JAVA_MAIN_CLASS" - envVarAppJAR = "JAVA_APP_JAR" - defaultMainClass = "org.apache.camel.k.main.Application" ) func newEnvironmentTrait() *environmentTrait { @@ -69,13 +66,6 @@ func (t *environmentTrait) Apply(e *Environment) error { envvar.SetValFrom(&e.EnvVars, envVarPodName, "metadata.name") } - quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait) - if quarkus.isEnabled() { - quarkus.addContainerEnvironment(e) - } else { - envvar.SetVal(&e.EnvVars, envVarMainClass, defaultMainClass) - } - return nil } diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go index 9e46b8e91a..c8146757b1 100644 --- a/pkg/trait/quarkus.go +++ b/pkg/trait/quarkus.go @@ -32,7 +32,6 @@ import ( "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/defaults" - "github.com/apache/camel-k/pkg/util/envvar" "github.com/apache/camel-k/pkg/util/maven" ) @@ -191,10 +190,6 @@ func (t *quarkusTrait) addRuntimeDependencies(e *Environment) error { return nil } -func (t *quarkusTrait) addContainerEnvironment(e *Environment) { - envvar.SetVal(&e.EnvVars, envVarAppJAR, "camel-k-integration-"+defaults.Version+"-runner.jar") -} - func addRuntimeDependency(dependency string, dependencies *[]string) { util.StringSliceUniqueAdd(dependencies, fmt.Sprintf("mvn:org.apache.camel.k/%s", dependency)) } diff --git a/pkg/trait/quarkus_test.go b/pkg/trait/quarkus_test.go index dbc3aedddd..c368d7e19e 100644 --- a/pkg/trait/quarkus_test.go +++ b/pkg/trait/quarkus_test.go @@ -24,7 +24,6 @@ import ( "github.com/apache/camel-k/pkg/builder" "github.com/apache/camel-k/pkg/util/camel" - "github.com/apache/camel-k/pkg/util/envvar" "github.com/stretchr/testify/assert" ) @@ -107,14 +106,6 @@ func TestQuarkusTraitAddRuntimeDependenciesWithouSourceDoesNothing(t *testing.T) assert.Len(t, environment.Integration.Status.Dependencies, 0) } -func TestQuarkusTraitAddContainerEnvironmentShouldSucceed(t *testing.T) { - quarkusTrait, environment := createNominalQuarkusTest() - - quarkusTrait.addContainerEnvironment(environment) - - assert.NotNil(t, envvar.Get(environment.EnvVars, envVarAppJAR)) -} - func TestQuarkusTraitAddRuntimeDependencyShouldSucceed(t *testing.T) { dependency := "depA" dependencies := make([]string, 0) From 169013a22d5b7d5dff5a4e1ade9741e59f6a8cdb Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 16:27:28 +0100 Subject: [PATCH 05/13] chore(trait): Set integration container working directory --- pkg/trait/classpath.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index bbbe845836..0405ee3256 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -108,21 +108,26 @@ func (t *classpathTrait) Apply(e *Environment) error { container := e.Resources.GetContainerByName(containerName) if container != nil { + // Add mounted resources to the class path for _, m := range container.VolumeMounts { classpath.Add(m.MountPath) } items := classpath.List() - // keep classpath sorted + // Keep class path sorted so that it's consistent over reconciliation cycles sort.Strings(items) container.Args = append(container.Args, "-cp", strings.Join(items, ":")) + // Add main Class or JAR quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait) if quarkus.isEnabled() { container.Args = append(container.Args, "-jar", "camel-k-integration-"+defaults.Version+"-runner.jar") } else { container.Args = append(container.Args, defaultMainClass) } + + // Set the container working directory + container.WorkingDir = "/deployments" } return nil From 24248d974091c8c8cd73be53928997728fa5c2a6 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 16:28:49 +0100 Subject: [PATCH 06/13] feat(dev): Use adoptopenjdk/openjdk8:slim as base image for the Camel K operator --- build/Dockerfile | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index c0601a607f..b8b0a0bd6e 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -13,13 +13,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM fabric8/s2i-java:3.0-java8 +FROM adoptopenjdk/openjdk8:slim + +ARG MAVEN_VERSION="3.6.3" +ARG SHA="c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0" +ARG BASE_URL="https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries" + +RUN mkdir -p /usr/share/maven \ + && curl -Lso /tmp/maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ + && echo "${SHA} /tmp/maven.tar.gz" | sha512sum -c - \ + && tar -xzC /usr/share/maven --strip-components=1 -f /tmp/maven.tar.gz \ + && rm -v /tmp/maven.tar.gz \ + && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn ADD build/_maven_output /tmp/artifacts/m2 USER 0 + RUN chgrp -R 0 /tmp/artifacts/m2 \ - && chmod -R g=u /tmp/artifacts/m2 + && chmod -R g=u /tmp/artifacts/m2 USER 1000 From 737ca444c9857115047fff61a689788d2c3bf777 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Fri, 17 Jan 2020 16:30:18 +0100 Subject: [PATCH 07/13] feat(dev): Use adoptopenjdk/openjdk8:slim as base image for integrations --- pkg/util/defaults/defaults.go | 2 +- script/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/util/defaults/defaults.go b/pkg/util/defaults/defaults.go index 95b525a145..68e4813a30 100644 --- a/pkg/util/defaults/defaults.go +++ b/pkg/util/defaults/defaults.go @@ -41,7 +41,7 @@ const ( KanikoVersion = "0.14.0" // BaseImage -- - BaseImage = "fabric8/s2i-java:3.0-java8" + BaseImage = "adoptopenjdk/openjdk8:slim" // LocalRepository -- LocalRepository = "/tmp/artifacts/m2" diff --git a/script/Makefile b/script/Makefile index cdfd88aabb..84ef49157f 100644 --- a/script/Makefile +++ b/script/Makefile @@ -21,7 +21,7 @@ CAMEL_VERSION := 3.0.0 CAMEL_QUARKUS_VERSION := 1.0.0-M2 QUARKUS_VERSION := 1.1.0.Final KANIKO_VERSION := 0.14.0 -BASE_IMAGE := fabric8/s2i-java:3.0-java8 +BASE_IMAGE := adoptopenjdk/openjdk8:slim LOCAL_REPOSITORY := /tmp/artifacts/m2 IMAGE_NAME := docker.io/apache/camel-k RELEASE_GIT_REMOTE := upstream From 4aeeae1a6f123d09c9493ac4394bd06933c38f0b Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Tue, 21 Jan 2020 10:19:22 +0100 Subject: [PATCH 08/13] fix(build): Use Docker build strategy in S2I builds --- pkg/builder/s2i/publisher.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/builder/s2i/publisher.go b/pkg/builder/s2i/publisher.go index d3afb3adf4..9e346e7675 100644 --- a/pkg/builder/s2i/publisher.go +++ b/pkg/builder/s2i/publisher.go @@ -22,6 +22,8 @@ import ( "os" "path" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -35,11 +37,17 @@ import ( "github.com/apache/camel-k/pkg/builder" "github.com/apache/camel-k/pkg/util/kubernetes" "github.com/apache/camel-k/pkg/util/kubernetes/customclient" - - "github.com/pkg/errors" ) func publisher(ctx *builder.Context) error { + // We may want to unify the Dockerfile between build strategies, i.e., between Kaniko and S2I + // #nosec G202 + dockerfile := ` + FROM ` + ctx.BaseImage + ` + ADD . /deployments + USER 1000 + ` + bc := buildv1.BuildConfig{ TypeMeta: metav1.TypeMeta{ APIVersion: buildv1.GroupVersion.String(), @@ -55,15 +63,11 @@ func publisher(ctx *builder.Context) error { Spec: buildv1.BuildConfigSpec{ CommonSpec: buildv1.CommonSpec{ Source: buildv1.BuildSource{ - Type: buildv1.BuildSourceBinary, + Type: buildv1.BuildSourceBinary, + Dockerfile: &dockerfile, }, Strategy: buildv1.BuildStrategy{ - SourceStrategy: &buildv1.SourceBuildStrategy{ - From: corev1.ObjectReference{ - Kind: "DockerImage", - Name: ctx.BaseImage, - }, - }, + DockerStrategy: &buildv1.DockerBuildStrategy{}, }, Output: buildv1.BuildOutput{ To: &corev1.ObjectReference{ From 92bfd51930244efa224dbddcdf3f3c13fda1a2a9 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Tue, 21 Jan 2020 11:44:28 +0100 Subject: [PATCH 09/13] chore(trait): Use container args to configure JVM debugging --- pkg/trait/classpath.go | 12 ++---------- pkg/trait/debug.go | 14 +++++++++----- pkg/trait/debug_test.go | 29 ++++++++++++++++++++++++----- pkg/trait/jolokia.go | 8 +------- pkg/trait/prometheus.go | 8 +------- pkg/trait/quarkus.go | 4 ---- pkg/trait/trait_catalog.go | 6 +++--- pkg/trait/trait_types.go | 10 ++++++++++ 8 files changed, 50 insertions(+), 41 deletions(-) diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index 0405ee3256..71b7cc4609 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -85,9 +85,7 @@ func (t *classpathTrait) Apply(e *Environment) error { classpath.Add("./resources") quarkus := e.Catalog.GetTrait("quarkus").(*quarkusTrait) - if quarkus.isEnabled() { - quarkus.addClasspath(e) - } else { + if !quarkus.isEnabled() { for _, artifact := range kit.Status.Artifacts { classpath.Add(artifact.Target) } @@ -100,13 +98,7 @@ func (t *classpathTrait) Apply(e *Environment) error { classpath.Add("/deployments/dependencies/*") } - containerName := defaultContainerName - dt := e.Catalog.GetTrait(containerTraitID) - if dt != nil { - containerName = dt.(*containerTrait).Name - } - - container := e.Resources.GetContainerByName(containerName) + container := e.getIntegrationContainer() if container != nil { // Add mounted resources to the class path for _, m := range container.VolumeMounts { diff --git a/pkg/trait/debug.go b/pkg/trait/debug.go index 9ecaed8f5b..38d3c5fa47 100644 --- a/pkg/trait/debug.go +++ b/pkg/trait/debug.go @@ -18,15 +18,14 @@ limitations under the License. package trait import ( + "fmt" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/envvar" ) // The Debug trait can be used to enable debugging on the integration container, // so that a remote debugger can be attached. // -// Enabling the trait will inject the `JAVA_DEBUG` environment variable into the integration container. -// // +camel-k:trait=debug type debugTrait struct { BaseTrait `property:",squash"` @@ -47,8 +46,13 @@ func (t *debugTrait) Configure(e *Environment) (bool, error) { } func (t *debugTrait) Apply(e *Environment) error { - // this is all that's needed as long as the base image is `fabric8/s2i-java` look into builder/builder.go - envvar.SetVal(&e.EnvVars, "JAVA_DEBUG", True) + container := e.getIntegrationContainer() + if container == nil { + return fmt.Errorf("unable to find integration container") + } + + // TODO: Add options to configure debugging agent + container.Args = append(container.Args, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005") return nil } diff --git a/pkg/trait/debug_test.go b/pkg/trait/debug_test.go index 71ea9d1f4a..32b3e1dea7 100644 --- a/pkg/trait/debug_test.go +++ b/pkg/trait/debug_test.go @@ -18,15 +18,17 @@ limitations under the License. package trait import ( + "context" "testing" "github.com/stretchr/testify/assert" + 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/envvar" + "github.com/apache/camel-k/pkg/util/kubernetes" ) func TestDebugTraitApplicability(t *testing.T) { @@ -49,7 +51,6 @@ func TestDebugTraitApplicability(t *testing.T) { }, }, }, - EnvVars: make([]corev1.EnvVar, 0), } trait := newDebugTrait() @@ -67,6 +68,7 @@ func TestDebugTraitApplicability(t *testing.T) { func TestApplyDebugTrait(t *testing.T) { environment := Environment{ + Catalog: NewCatalog(context.TODO(), nil), Integration: &v1.Integration{ Status: v1.IntegrationStatus{ Phase: v1.IntegrationPhaseDeploying, @@ -81,12 +83,29 @@ func TestApplyDebugTrait(t *testing.T) { }, }, }, - EnvVars: make([]corev1.EnvVar, 0), + Resources: kubernetes.NewCollection(), } + d := appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: defaultContainerName, + }, + }, + }, + }, + }, + } + + environment.Resources.Add(&d) + trait := newDebugTrait() assert.Nil(t, trait.Apply(&environment)) - assert.NotNil(t, envvar.Get(environment.EnvVars, "JAVA_DEBUG")) - assert.Equal(t, True, envvar.Get(environment.EnvVars, "JAVA_DEBUG").Value) + assert.Equal(t, d.Spec.Template.Spec.Containers[0].Args, []string{ + "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005", + }) } diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go index 5022d90f31..4f1ef04f84 100644 --- a/pkg/trait/jolokia.go +++ b/pkg/trait/jolokia.go @@ -128,13 +128,7 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { return nil } - containerName := defaultContainerName - dt := e.Catalog.GetTrait(containerTraitID) - if dt != nil { - containerName = dt.(*containerTrait).Name - } - - container := e.Resources.GetContainerByName(containerName) + container := e.getIntegrationContainer() if container == nil { e.Integration.Status.SetCondition( v1.IntegrationConditionJolokiaAvailable, diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go index b995f6308f..f4898746b3 100644 --- a/pkg/trait/prometheus.go +++ b/pkg/trait/prometheus.go @@ -68,13 +68,7 @@ func (t *prometheusTrait) Configure(e *Environment) (bool, error) { } func (t *prometheusTrait) Apply(e *Environment) (err error) { - containerName := defaultContainerName - dt := e.Catalog.GetTrait(containerTraitID) - if dt != nil { - containerName = dt.(*containerTrait).Name - } - - container := e.Resources.GetContainerByName(containerName) + 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 c8146757b1..50e9c1fe97 100644 --- a/pkg/trait/quarkus.go +++ b/pkg/trait/quarkus.go @@ -148,10 +148,6 @@ func (t *quarkusTrait) addBuildSteps(task *v1.BuilderTask) { task.Steps = append(task.Steps, builder.StepIDsFor(runtime.QuarkusSteps...)...) } -func (t *quarkusTrait) addClasspath(_ *Environment) { - // No-op as we rely on the Quarkus runner -} - func (t *quarkusTrait) addRuntimeDependencies(e *Environment) error { dependencies := &e.Integration.Status.Dependencies diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go index 42b2069828..a045f3085f 100644 --- a/pkg/trait/trait_catalog.go +++ b/pkg/trait/trait_catalog.go @@ -151,7 +151,6 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { return []Trait{ c.tPlatform, c.tCamel, - c.tDebug, c.tRestDsl, c.tDependencies, c.tBuilder, @@ -167,6 +166,7 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { c.tPullSecret, c.tJolokia, c.tPrometheus, + c.tDebug, c.tClasspath, c.tProbes, c.tRoute, @@ -177,7 +177,6 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { return []Trait{ c.tPlatform, c.tCamel, - c.tDebug, c.tRestDsl, c.tDependencies, c.tBuilder, @@ -193,6 +192,7 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { c.tPullSecret, c.tJolokia, c.tPrometheus, + c.tDebug, c.tClasspath, c.tProbes, c.tIngress, @@ -203,7 +203,6 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { return []Trait{ c.tPlatform, c.tCamel, - c.tDebug, c.tRestDsl, c.tKnative, c.tDependencies, @@ -220,6 +219,7 @@ func (c *Catalog) TraitsForProfile(profile v1.TraitProfile) []Trait { c.tPullSecret, c.tJolokia, c.tPrometheus, + c.tDebug, c.tClasspath, c.tProbes, c.tIstio, diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index de8a6c9c94..f3c8e4bace 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -613,3 +613,13 @@ func (e *Environment) CollectConfigurationValues(configurationType string) []str func (e *Environment) CollectConfigurationPairs(configurationType string) map[string]string { return CollectConfigurationPairs(configurationType, e.Platform, e.IntegrationKit, e.Integration) } + +func (e *Environment) getIntegrationContainer() *corev1.Container { + containerName := defaultContainerName + dt := e.Catalog.GetTrait(containerTraitID) + if dt != nil { + containerName = dt.(*containerTrait).Name + } + + return e.Resources.GetContainerByName(containerName) +} From 34a18551e554ff3a8c9916f73185200341270ba0 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Tue, 21 Jan 2020 15:32:26 +0100 Subject: [PATCH 10/13] chore(trait): Use container args to configure Jolokia agent --- pkg/trait/jolokia.go | 71 ++++++++++------------- pkg/trait/jolokia_test.go | 118 ++++++++++++-------------------------- 2 files changed, 65 insertions(+), 124 deletions(-) diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go index 4f1ef04f84..e08eca03d0 100644 --- a/pkg/trait/jolokia.go +++ b/pkg/trait/jolokia.go @@ -26,7 +26,6 @@ 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/envvar" ) // The Jolokia trait activates and configures the Jolokia Java agent. @@ -84,35 +83,7 @@ func (t *jolokiaTrait) isEnabled() bool { } func (t *jolokiaTrait) Configure(e *Environment) (bool, error) { - options, err := parseCsvMap(t.Options) - if err != nil { - return false, err - } - - if len(t.ClientPrincipal) == 1 { - // Work-around the lack of proper support for multi-valued trait options from the CLI - t.ClientPrincipal = strings.Split(t.ClientPrincipal[0], ",") - } - - setDefaultJolokiaOption(options, &t.Host, "host", "*") - setDefaultJolokiaOption(options, &t.DiscoveryEnabled, "discoveryEnabled", false) - - // Configure HTTPS by default for OpenShift - if e.DetermineProfile() == v1.TraitProfileOpenShift { - setDefaultJolokiaOption(options, &t.Protocol, "protocol", "https") - setDefaultJolokiaOption(options, &t.CaCert, "caCert", "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt") - setDefaultJolokiaOption(options, &t.ExtendedClientCheck, "extendedClientCheck", true) - setDefaultJolokiaOption(options, &t.UseSslClientAuthentication, "useSslClientAuthentication", true) - setDefaultJolokiaOption(options, &t.ClientPrincipal, "clientPrincipal", []string{ - // Master API proxy for OpenShift 3 - "cn=system:master-proxy", - // Default Hawtio and Fuse consoles for OpenShift 4 - "cn=hawtio-online.hawtio.svc", - "cn=fuse-console.fuse.svc", - }) - } - - return e.IntegrationInPhase( + return t.isEnabled() && e.IntegrationInPhase( v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning, @@ -124,6 +95,9 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { if t.isEnabled() { // Add Camel management dependency util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-management") + // And Jolokia agent + // TODO: We may want to make the Jolokia version configurable + util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.jolokia/jolokia-jvm:jar:agent:1.6.2") } return nil } @@ -139,16 +113,6 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { return nil } - if !t.isEnabled() { - // Deactivate the Jolokia Java agent - // Note: the AB_JOLOKIA_OFF environment variable acts as an option flag - envvar.SetVal(&container.Env, "AB_JOLOKIA_OFF", "true") - return nil - } - - // Need to set it explicitly as it default to true - envvar.SetVal(&container.Env, "AB_JOLOKIA_AUTH_OPENSHIFT", "false") - // Configure the Jolokia Java agent // Populate first with the extra options options, err := parseCsvMap(t.Options) @@ -156,6 +120,29 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { return err } + if len(t.ClientPrincipal) == 1 { + // Work-around the lack of proper support for multi-valued trait options from the CLI + t.ClientPrincipal = strings.Split(t.ClientPrincipal[0], ",") + } + + setDefaultJolokiaOption(options, &t.Host, "host", "*") + setDefaultJolokiaOption(options, &t.DiscoveryEnabled, "discoveryEnabled", false) + + // Configure HTTPS by default for OpenShift + if e.DetermineProfile() == v1.TraitProfileOpenShift { + setDefaultJolokiaOption(options, &t.Protocol, "protocol", "https") + setDefaultJolokiaOption(options, &t.CaCert, "caCert", "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt") + setDefaultJolokiaOption(options, &t.ExtendedClientCheck, "extendedClientCheck", true) + setDefaultJolokiaOption(options, &t.UseSslClientAuthentication, "useSslClientAuthentication", true) + setDefaultJolokiaOption(options, &t.ClientPrincipal, "clientPrincipal", []string{ + // Master API proxy for OpenShift 3 + "cn=system:master-proxy", + // Default Hawtio and Fuse consoles for OpenShift 4 + "cn=hawtio-online.hawtio.svc", + "cn=fuse-console.fuse.svc", + }) + } + // Then add explicitly set trait configuration properties addToJolokiaOptions(options, "caCert", t.CaCert) addToJolokiaOptions(options, "clientPrincipal", t.ClientPrincipal) @@ -168,14 +155,14 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { addToJolokiaOptions(options, "user", t.User) addToJolokiaOptions(options, "useSslClientAuthentication", t.UseSslClientAuthentication) - // Lastly set the AB_JOLOKIA_OPTS environment variable from the fabric8/s2i-java base image // Options must be sorted so that the environment variable value is consistent over iterations, // otherwise the value changes which results in triggering a new deployment. optionValues := make([]string, len(options)) for i, k := range util.SortedStringMapKeys(options) { optionValues[i] = k + "=" + options[k] } - envvar.SetVal(&container.Env, "AB_JOLOKIA_OPTS", strings.Join(optionValues, ",")) + + container.Args = append(container.Args, "-javaagent:dependencies/org.jolokia.jolokia-jvm-1.6.2-agent.jar="+strings.Join(optionValues, ",")) containerPort := corev1.ContainerPort{ Name: "jolokia", diff --git a/pkg/trait/jolokia_test.go b/pkg/trait/jolokia_test.go index bbaf4e4644..63e0fe822a 100644 --- a/pkg/trait/jolokia_test.go +++ b/pkg/trait/jolokia_test.go @@ -21,105 +21,69 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + 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/envvar" "github.com/apache/camel-k/pkg/util/kubernetes" - "github.com/apache/camel-k/pkg/util/test" - - "github.com/stretchr/testify/assert" ) -func TestConfigureJolokiaTraitInRightPhaseDoesSucceed(t *testing.T) { +func TestConfigureJolokiaTraitInRunningPhaseDoesSucceed(t *testing.T) { trait, environment := createNominalJolokiaTest() + environment.Integration.Status.Phase = v1.IntegrationPhaseRunning configured, err := trait.Configure(environment) assert.Nil(t, err) assert.True(t, configured) - assert.Equal(t, *trait.Host, "*") - assert.Equal(t, *trait.DiscoveryEnabled, false) - assert.Nil(t, trait.Protocol) - assert.Nil(t, trait.CaCert) - assert.Nil(t, trait.ExtendedClientCheck) - assert.Nil(t, trait.ClientPrincipal) - assert.Nil(t, trait.UseSslClientAuthentication) } -func TestConfigureJolokiaTraitInWrongPhaseDoesNotSucceed(t *testing.T) { +func TestApplyJolokiaTraitNominalShouldSucceed(t *testing.T) { trait, environment := createNominalJolokiaTest() - environment.Integration.Status.Phase = v1.IntegrationPhaseRunning - configured, err := trait.Configure(environment) + err := trait.Apply(environment) assert.Nil(t, err) - assert.True(t, configured) -} - -func TestConfigureJolokiaTraitWithUnparseableOptionsDoesNotSucceed(t *testing.T) { - trait, environment := createNominalJolokiaTest() - options := "unparseable csv" - trait.Options = &options - configured, err := trait.Configure(environment) - assert.NotNil(t, err) - assert.False(t, configured) -} + container := environment.Resources.GetContainerByName(defaultContainerName) + assert.NotNil(t, container) -func TestConfigureJolokiaTraitForOpenShiftProfileShouldSetDefaultHttpsJolokiaOptions(t *testing.T) { - trait, environment := createNominalJolokiaTest() - environment.IntegrationKit.Spec.Profile = v1.TraitProfileOpenShift + assert.Equal(t, container.Args, []string{ + "-javaagent:dependencies/org.jolokia.jolokia-jvm-1.6.2-agent.jar=discoveryEnabled=false,host=*,port=8778", + }) - configured, err := trait.Configure(environment) + assert.Len(t, container.Ports, 1) + containerPort := container.Ports[0] + assert.Equal(t, "jolokia", containerPort.Name) + assert.Equal(t, int32(8778), containerPort.ContainerPort) + assert.Equal(t, corev1.ProtocolTCP, containerPort.Protocol) - assert.Nil(t, err) - assert.True(t, configured) - assert.Equal(t, *trait.Protocol, "https") - assert.Equal(t, *trait.CaCert, "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt") - assert.Equal(t, *trait.ExtendedClientCheck, true) - assert.Equal(t, *trait.UseSslClientAuthentication, true) + assert.Len(t, environment.Integration.Status.Conditions, 1) + condition := environment.Integration.Status.Conditions[0] + assert.Equal(t, v1.IntegrationConditionJolokiaAvailable, condition.Type) + assert.Equal(t, corev1.ConditionTrue, condition.Status) } -func TestConfigureJolokiaTraitWithOptionsShouldPreventDefaultJolokiaOptions(t *testing.T) { +func TestApplyJolokiaTraitForOpenShiftProfileShouldSucceed(t *testing.T) { trait, environment := createNominalJolokiaTest() environment.IntegrationKit.Spec.Profile = v1.TraitProfileOpenShift - options := "host=explicit-host," + - "discoveryEnabled=true," + - "protocol=http," + - "caCert=.cacert," + - "extendedClientCheck=false," + - "clientPrincipal=cn:any," + - "useSslClientAuthentication=false" - trait.Options = &options - configured, err := trait.Configure(environment) + err := trait.Apply(environment) assert.Nil(t, err) - assert.True(t, configured) - assert.Nil(t, trait.Host) - assert.Nil(t, trait.DiscoveryEnabled) - assert.Nil(t, trait.Protocol) - assert.Nil(t, trait.CaCert) - assert.Nil(t, trait.ExtendedClientCheck) - assert.Nil(t, trait.ClientPrincipal) - assert.Nil(t, trait.UseSslClientAuthentication) -} - -func TestApplyJolokiaTraitNominalShouldSucceed(t *testing.T) { - trait, environment := createNominalJolokiaTest() - - err := trait.Apply(environment) container := environment.Resources.GetContainerByName(defaultContainerName) + assert.NotNil(t, container) - assert.Nil(t, err) - test.EnvVarHasValue(t, container.Env, "AB_JOLOKIA_AUTH_OPENSHIFT", "false") - test.EnvVarHasValue(t, container.Env, "AB_JOLOKIA_OPTS", "port=8778") - assert.Len(t, environment.Integration.Status.Conditions, 1) + assert.Equal(t, container.Args, []string{ + "-javaagent:dependencies/org.jolokia.jolokia-jvm-1.6.2-agent.jar=caCert=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt," + + "clientPrincipal.1=cn=system:master-proxy,clientPrincipal.2=cn=hawtio-online.hawtio.svc," + + "clientPrincipal.3=cn=fuse-console.fuse.svc,discoveryEnabled=false,extendedClientCheck=true," + + "host=*,port=8778,protocol=https,useSslClientAuthentication=true", + }) - assert.NotNil(t, container) assert.Len(t, container.Ports, 1) containerPort := container.Ports[0] assert.Equal(t, "jolokia", containerPort.Name) @@ -158,13 +122,15 @@ func TestApplyJolokiaTraitWithOptionShouldOverrideDefault(t *testing.T) { err := trait.Apply(environment) + assert.Nil(t, err) + container := environment.Resources.GetContainerByName(defaultContainerName) - assert.Nil(t, err) - ev := envvar.Get(container.Env, "AB_JOLOKIA_OPTS") - assert.NotNil(t, ev) - assert.Contains(t, ev.Value, "port=8778", "host=explicit-host", "discoveryEnabled=true", "protocol=http", "caCert=.cacert") - assert.Contains(t, ev.Value, "extendedClientCheck=false", "clientPrincipal=cn:any", "useSslClientAuthentication=false") + assert.Equal(t, container.Args, []string{ + "-javaagent:dependencies/org.jolokia.jolokia-jvm-1.6.2-agent.jar=caCert=.cacert,clientPrincipal=cn:any," + + "discoveryEnabled=true,extendedClientCheck=false,host=explicit-host,port=8778,protocol=http," + + "useSslClientAuthentication=false", + }) } func TestApplyJolokiaTraitWithUnparseableOptionShouldReturnError(t *testing.T) { @@ -177,18 +143,6 @@ func TestApplyJolokiaTraitWithUnparseableOptionShouldReturnError(t *testing.T) { assert.NotNil(t, err) } -func TestApplyDisabledJolokiaTraitShouldNotSucceed(t *testing.T) { - trait, environment := createNominalJolokiaTest() - trait.Enabled = new(bool) - - err := trait.Apply(environment) - - container := environment.Resources.GetContainerByName(defaultContainerName) - - assert.Nil(t, err) - test.EnvVarHasValue(t, container.Env, "AB_JOLOKIA_OFF", "true") -} - func TestSetDefaultJolokiaOptionShoudlNotOverrideOptionsMap(t *testing.T) { options := map[string]string{"key": "value"} optionValue := "" From 2467cc3f0f4669bd1dc1ebcd5cd45b71b180ea88 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Wed, 22 Jan 2020 08:54:46 +0100 Subject: [PATCH 11/13] chore(trait): Update Jolokia trait documentation --- docs/modules/ROOT/pages/traits/debug.adoc | 2 -- .../ROOT/pages/traits/environment.adoc | 2 +- docs/modules/ROOT/pages/traits/jolokia.adoc | 6 ++-- pkg/trait/jolokia.go | 28 ++++++------------- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/docs/modules/ROOT/pages/traits/debug.adoc b/docs/modules/ROOT/pages/traits/debug.adoc index 1ac28e4f58..8cb42af7f5 100755 --- a/docs/modules/ROOT/pages/traits/debug.adoc +++ b/docs/modules/ROOT/pages/traits/debug.adoc @@ -4,8 +4,6 @@ The Debug trait can be used to enable debugging on the integration container, so that a remote debugger can be attached. -Enabling the trait will inject the `JAVA_DEBUG` environment variable into the integration container. - This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. diff --git a/docs/modules/ROOT/pages/traits/environment.adoc b/docs/modules/ROOT/pages/traits/environment.adoc index 51c65b0dc3..283e8317f5 100755 --- a/docs/modules/ROOT/pages/traits/environment.adoc +++ b/docs/modules/ROOT/pages/traits/environment.adoc @@ -2,7 +2,7 @@ // Start of autogenerated code - DO NOT EDIT! (description) The environment trait is used internally to inject standard environment variables in the integration container, -such as `NAMESPACE`, `POD_NAME`, `JAVA_MAIN_CLASS` and others. +such as `NAMESPACE`, `POD_NAME` and others. This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. diff --git a/docs/modules/ROOT/pages/traits/jolokia.adoc b/docs/modules/ROOT/pages/traits/jolokia.adoc index 9d1f0edc9d..e8b1e8ac5c 100755 --- a/docs/modules/ROOT/pages/traits/jolokia.adoc +++ b/docs/modules/ROOT/pages/traits/jolokia.adoc @@ -30,13 +30,13 @@ The following configuration options are available: | string | The PEM encoded CA certification file path, used to verify client certificates, applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true` -(default `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt` for OpenShift). +(default `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` for OpenShift). | jolokia.client-principal | []string -| The principal which must be given in a client certificate to allow access to the Jolokia endpoint, +| The principal(s) which must be given in a client certificate to allow access to the Jolokia endpoint, applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true` -(default `clientPrincipal=cn=system:master-proxy` for OpenShift). +(default `clientPrincipal=cn=system:master-proxy`, `cn=hawtio-online.hawtio.svc` and `cn=fuse-console.fuse.svc` for OpenShift). | jolokia.discovery-enabled | bool diff --git a/pkg/trait/jolokia.go b/pkg/trait/jolokia.go index e08eca03d0..00f6f8a5e1 100644 --- a/pkg/trait/jolokia.go +++ b/pkg/trait/jolokia.go @@ -37,11 +37,11 @@ type jolokiaTrait struct { BaseTrait `property:",squash"` // The PEM encoded CA certification file path, used to verify client certificates, // applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true` - // (default `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt` for OpenShift). + // (default `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` for OpenShift). CaCert *string `property:"ca-cert"` - // The principal which must be given in a client certificate to allow access to the Jolokia endpoint, + // The principal(s) which must be given in a client certificate to allow access to the Jolokia endpoint, // applicable when `protocol` is `https` and `use-ssl-client-authentication` is `true` - // (default `clientPrincipal=cn=system:master-proxy` for OpenShift). + // (default `clientPrincipal=cn=system:master-proxy`, `cn=hawtio-online.hawtio.svc` and `cn=fuse-console.fuse.svc` for OpenShift). ClientPrincipal []string `property:"client-principal"` // Listen for multicast requests (default `false`) DiscoveryEnabled *bool `property:"discovery-enabled"` @@ -69,8 +69,6 @@ type jolokiaTrait struct { Options *string `property:"options"` } -// The Jolokia trait must be executed prior to the deployment trait -// as it mutates environment variables func newJolokiaTrait() *jolokiaTrait { return &jolokiaTrait{ BaseTrait: newBaseTrait("jolokia"), @@ -78,12 +76,8 @@ func newJolokiaTrait() *jolokiaTrait { } } -func (t *jolokiaTrait) isEnabled() bool { - return t.Enabled != nil && *t.Enabled -} - func (t *jolokiaTrait) Configure(e *Environment) (bool, error) { - return t.isEnabled() && e.IntegrationInPhase( + return t.Enabled != nil && *t.Enabled && e.IntegrationInPhase( v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning, @@ -92,13 +86,10 @@ func (t *jolokiaTrait) Configure(e *Environment) (bool, error) { func (t *jolokiaTrait) Apply(e *Environment) (err error) { if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { - if t.isEnabled() { - // Add Camel management dependency - util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-management") - // And Jolokia agent - // TODO: We may want to make the Jolokia version configurable - util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.jolokia/jolokia-jvm:jar:agent:1.6.2") - } + // Add the Camel management and Jolokia agent dependencies + util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-management") + // TODO: We may want to make the Jolokia version configurable + util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.jolokia/jolokia-jvm:jar:agent:1.6.2") return nil } @@ -113,8 +104,7 @@ func (t *jolokiaTrait) Apply(e *Environment) (err error) { return nil } - // Configure the Jolokia Java agent - // Populate first with the extra options + // Configure the Jolokia Java agent, first with the extra options options, err := parseCsvMap(t.Options) if err != nil { return err From 55296eb914f65f744b440ec9916c4c9374b648f2 Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Wed, 22 Jan 2020 12:01:02 +0100 Subject: [PATCH 12/13] chore(it): Report generated resources in integration status --- pkg/apis/camel/v1/integration_types.go | 33 ++++++++++--------- .../camel/v1/integration_types_support.go | 17 +++++++--- pkg/apis/camel/v1/zz_generated.deepcopy.go | 5 +++ pkg/trait/trait_types.go | 2 +- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go index dcb2739e0d..e62710c525 100644 --- a/pkg/apis/camel/v1/integration_types.go +++ b/pkg/apis/camel/v1/integration_types.go @@ -40,22 +40,23 @@ type IntegrationSpec struct { // IntegrationStatus defines the observed state of Integration type IntegrationStatus struct { - Phase IntegrationPhase `json:"phase,omitempty"` - Digest string `json:"digest,omitempty"` - Image string `json:"image,omitempty"` - Dependencies []string `json:"dependencies,omitempty"` - Profile TraitProfile `json:"profile,omitempty"` - Kit string `json:"kit,omitempty"` - Platform string `json:"platform,omitempty"` - GeneratedSources []SourceSpec `json:"generatedSources,omitempty"` - Failure *Failure `json:"failure,omitempty"` - CamelVersion string `json:"camelVersion,omitempty"` - RuntimeVersion string `json:"runtimeVersion,omitempty"` - RuntimeProvider *RuntimeProvider `json:"runtimeProvider,omitempty"` - Configuration []ConfigurationSpec `json:"configuration,omitempty"` - Conditions []IntegrationCondition `json:"conditions,omitempty"` - Version string `json:"version,omitempty"` - Replicas *int32 `json:"replicas,omitempty"` + Phase IntegrationPhase `json:"phase,omitempty"` + Digest string `json:"digest,omitempty"` + Image string `json:"image,omitempty"` + Dependencies []string `json:"dependencies,omitempty"` + Profile TraitProfile `json:"profile,omitempty"` + Kit string `json:"kit,omitempty"` + Platform string `json:"platform,omitempty"` + GeneratedSources []SourceSpec `json:"generatedSources,omitempty"` + GeneratedResources []ResourceSpec `json:"generatedResources,omitempty"` + Failure *Failure `json:"failure,omitempty"` + CamelVersion string `json:"camelVersion,omitempty"` + RuntimeVersion string `json:"runtimeVersion,omitempty"` + RuntimeProvider *RuntimeProvider `json:"runtimeProvider,omitempty"` + Configuration []ConfigurationSpec `json:"configuration,omitempty"` + Conditions []IntegrationCondition `json:"conditions,omitempty"` + Version string `json:"version,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go index f7238840b5..2b2e61f96f 100644 --- a/pkg/apis/camel/v1/integration_types_support.go +++ b/pkg/apis/camel/v1/integration_types_support.go @@ -50,11 +50,20 @@ func NewIntegrationList() IntegrationList { // Sources return a new slice containing all the sources associated to the integration func (in *Integration) Sources() []SourceSpec { - allSources := make([]SourceSpec, 0, len(in.Spec.Sources)+len(in.Status.GeneratedSources)) - allSources = append(allSources, in.Spec.Sources...) - allSources = append(allSources, in.Status.GeneratedSources...) + sources := make([]SourceSpec, 0, len(in.Spec.Sources)+len(in.Status.GeneratedSources)) + sources = append(sources, in.Spec.Sources...) + sources = append(sources, in.Status.GeneratedSources...) - return allSources + return sources +} + +// Resources return a new slice containing all the resources associated to the integration +func (in *Integration) Resources() []ResourceSpec { + resources := make([]ResourceSpec, 0, len(in.Spec.Resources)+len(in.Status.GeneratedResources)) + resources = append(resources, in.Spec.Resources...) + resources = append(resources, in.Status.GeneratedResources...) + + return resources } // AddSource -- diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go index 74c59ddcf4..0427675970 100644 --- a/pkg/apis/camel/v1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go @@ -1057,6 +1057,11 @@ func (in *IntegrationStatus) DeepCopyInto(out *IntegrationStatus) { *out = make([]SourceSpec, len(*in)) copy(*out, *in) } + if in.GeneratedResources != nil { + in, out := &in.GeneratedResources, &out.GeneratedResources + *out = make([]ResourceSpec, len(*in)) + copy(*out, *in) + } if in.Failure != nil { in, out := &in.Failure, &out.Failure *out = new(Failure) diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index f3c8e4bace..166421477b 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -456,7 +456,7 @@ func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c }) } - for i, r := range e.Integration.Spec.Resources { + for i, r := range e.Integration.Resources() { if r.Type != v1.ResourceTypeData { continue } From df71083fea461b0d4b1dcfca4d0c825927f2658d Mon Sep 17 00:00:00 2001 From: Antonin Stefanutti Date: Wed, 22 Jan 2020 15:53:55 +0100 Subject: [PATCH 13/13] chore(trait): Use container args to configure Prometheus agent --- deploy/prometheus-jmx-exporter.yaml | 586 +++++++++++++++ deploy/resources.go | 673 ++++++++++++++++-- .../modules/ROOT/pages/traits/prometheus.adoc | 9 +- .../camel/v1/integration_types_support.go | 20 + pkg/trait/prometheus.go | 83 ++- pkg/trait/prometheus_test.go | 26 +- 6 files changed, 1312 insertions(+), 85 deletions(-) create mode 100644 deploy/prometheus-jmx-exporter.yaml diff --git a/deploy/prometheus-jmx-exporter.yaml b/deploy/prometheus-jmx-exporter.yaml new file mode 100644 index 0000000000..aff0fc947d --- /dev/null +++ b/deploy/prometheus-jmx-exporter.yaml @@ -0,0 +1,586 @@ +startDelaySecs: 5 +ssl: false +blacklistObjectNames: ["java.lang:*"] +rules: + # Context level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + type: context + type: GAUGE + + + # Route level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + + # Processor level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + + # Consumers + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + consumer: $2 + type: consumers + type: GAUGE + + # Services + - pattern: 'org.apache.camel<>MaxDuration' + name: org.apache.camel.MaxDuration + help: Maximum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MeanDuration' + name: org.apache.camel.MeanDuration + help: Mean Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MinDuration' + name: org.apache.camel.MinDuration + help: Minimum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>TotalDuration' + name: org.apache.camel.TotalDuration + help: Total Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsBlocked' + name: org.apache.camel.ThreadsBlocked + help: Threads Blocked + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsInterrupted' + name: org.apache.camel.ThreadsInterrupted + help: Threads Interrupted + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 \ No newline at end of file diff --git a/deploy/resources.go b/deploy/resources.go index 60513dc816..04dc010bf3 100644 --- a/deploy/resources.go +++ b/deploy/resources.go @@ -19,8 +19,6 @@ limitations under the License. package deploy -var Resources map[string]string - func init() { Resources = make(map[string]string) @@ -7970,6 +7968,46 @@ spec: javaTypes: - org.apache.camel.dataformat.zipfile.ZipFileDataFormat +` + Resources["cr-example.yaml"] = + ` +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +apiVersion: camel.apache.org/v1 +kind: Integration +metadata: + name: example +spec: + sources: + - content: |- + // This is Camel K Groovy example route + + rnd = new Random() + + from('timer:groovy?period=1s') + .routeId('groovy') + .setBody() + .constant('Hello Camel K!') + .process { + it.in.headers['RandomValue'] = rnd.nextInt() + } + .to('log:info?showHeaders=true') + name: routes.groovy ` Resources["crd-build.yaml"] = ` @@ -8271,46 +8309,6 @@ spec: description: The number of pods JSONPath: .status.replicas -` - Resources["cr-example.yaml"] = - ` -# --------------------------------------------------------------------------- -# 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. -# --------------------------------------------------------------------------- - -apiVersion: camel.apache.org/v1 -kind: Integration -metadata: - name: example -spec: - sources: - - content: |- - // This is Camel K Groovy example route - - rnd = new Random() - - from('timer:groovy?period=1s') - .routeId('groovy') - .setBody() - .constant('Hello Camel K!') - .process { - it.in.headers['RandomValue'] = rnd.nextInt() - } - .to('log:info?showHeaders=true') - name: routes.groovy ` Resources["operator-deployment.yaml"] = ` @@ -9337,6 +9335,595 @@ spec: dependencies: - mvn:org.apache.camel.k/camel-k-runtime-main - mvn:org.apache.camel.k/camel-k-loader-yaml +` + Resources["prometheus-jmx-exporter.yaml"] = + ` +startDelaySecs: 5 +ssl: false +blacklistObjectNames: ["java.lang:*"] +rules: + # Context level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + type: context + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + type: context + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + type: context + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + type: context + type: GAUGE + + + # Route level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + route: $2 + type: routes + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + route: $2 + type: routes + type: GAUGE + + # Processor level + - pattern: 'org.apache.camel<>ExchangesCompleted' + name: org.apache.camel.ExchangesCompleted + help: Exchanges Completed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesFailed' + name: org.apache.camel.ExchangesFailed + help: Exchanges Failed + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesInflight' + name: org.apache.camel.ExchangesInflight + help: Exchanges Inflight + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>ExchangesTotal' + name: org.apache.camel.ExchangesTotal + help: Exchanges Total + type: COUNTER + labels: + context: $1 + processor: $2 + type: processors + - pattern: 'org.apache.camel<>FailuresHandled' + name: org.apache.camel.FailuresHandled + help: Failures Handled + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>ExternalRedeliveries' + name: org.apache.camel.ExternalRedeliveries + help: External Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + - pattern: 'org.apache.camel<>MaxProcessingTime' + name: org.apache.camel.MaxProcessingTime + help: Maximum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MeanProcessingTime' + name: org.apache.camel.MeanProcessingTime + help: Mean Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>MinProcessingTime' + name: org.apache.camel.MinProcessingTime + help: Minimum Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>LastProcessingTime' + name: org.apache.camel.LastProcessingTime + help: Last Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>DeltaProcessingTime' + name: org.apache.camel.DeltaProcessingTime + help: Delta Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>Redeliveries' + name: org.apache.camel.Redeliveries + help: Redeliveries + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>TotalProcessingTime' + name: org.apache.camel.TotalProcessingTime + help: Total Processing Time + labels: + context: $1 + processor: $2 + type: processors + type: GAUGE + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + processor: $2 + type: processors + type: COUNTER + + # Consumers + - pattern: 'org.apache.camel<>InflightExchanges' + name: org.apache.camel.InflightExchanges + help: Inflight Exchanges + labels: + context: $1 + consumer: $2 + type: consumers + type: GAUGE + + # Services + - pattern: 'org.apache.camel<>MaxDuration' + name: org.apache.camel.MaxDuration + help: Maximum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MeanDuration' + name: org.apache.camel.MeanDuration + help: Mean Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>MinDuration' + name: org.apache.camel.MinDuration + help: Minimum Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>TotalDuration' + name: org.apache.camel.TotalDuration + help: Total Duration + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsBlocked' + name: org.apache.camel.ThreadsBlocked + help: Threads Blocked + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.camel<>ThreadsInterrupted' + name: org.apache.camel.ThreadsInterrupted + help: Threads Interrupted + labels: + context: $1 + service: $2 + type: services + type: GAUGE + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumLogicalRuntimeFaults' + name: org.apache.cxf.NumLogicalRuntimeFaults + help: Number of logical runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>AvgResponseTime' + name: org.apache.cxf.AvgResponseTime + help: Average Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumInvocations' + name: org.apache.cxf.NumInvocations + help: Number of invocations + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MaxResponseTime' + name: org.apache.cxf.MaxResponseTime + help: Maximum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>MinResponseTime' + name: org.apache.cxf.MinResponseTime + help: Minimum Response Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>TotalHandlingTime' + name: org.apache.cxf.TotalHandlingTime + help: Total Handling Time + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumRuntimeFaults' + name: org.apache.cxf.NumRuntimeFaults + help: Number of runtime faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumUnCheckedApplicationFaults' + name: org.apache.cxf.NumUnCheckedApplicationFaults + help: Number of unchecked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 + operation: $5 + - pattern: 'org.apache.cxf<>NumCheckedApplicationFaults' + name: org.apache.cxf.NumCheckedApplicationFaults + help: Number of checked application faults + type: GAUGE + labels: + bus.id: $1 + type: $2 + service: $3 + port: $4 ` Resources["user-cluster-role.yaml"] = ` @@ -9374,3 +9961,5 @@ rules: ` } + +var Resources map[string]string diff --git a/docs/modules/ROOT/pages/traits/prometheus.adoc b/docs/modules/ROOT/pages/traits/prometheus.adoc index f358769cc3..ea5dfafea5 100755 --- a/docs/modules/ROOT/pages/traits/prometheus.adoc +++ b/docs/modules/ROOT/pages/traits/prometheus.adoc @@ -1,12 +1,11 @@ = Prometheus Trait // Start of autogenerated code - DO NOT EDIT! (description) -The Prometheus trait exposes the integration with a `Service` and a `ServiceMonitor` resources -so that the Prometheus endpoint can be scraped. +The Prometheus trait configures the Prometheus JMX exporter and exposes the integration with a `Service` +and a `ServiceMonitor` resources so that the Prometheus endpoint can be scraped. -WARNING: Creating the `ServiceMonitor` resource requires the https://github.com/coreos/prometheus-operator[Prometheus Operator] -custom resource definition to be installed. You can set `service-monitor` to `false` for the Prometheus trait to work without -the Prometheus operator. +WARNING: The creation of the `ServiceMonitor` resource requires the https://github.com/coreos/prometheus-operator[Prometheus Operator] custom resource definition to be installed. +You can set `service-monitor` to `false` for the Prometheus trait to work without the Prometheus operator. It's disabled by default. diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go index 2b2e61f96f..21b8c0e7fd 100644 --- a/pkg/apis/camel/v1/integration_types_support.go +++ b/pkg/apis/camel/v1/integration_types_support.go @@ -108,6 +108,26 @@ func (in *IntegrationSpec) AddDependency(dependency string) { in.Dependencies = append(in.Dependencies, newDep) } +// AddOrReplaceGeneratedResources -- +func (in *IntegrationStatus) AddOrReplaceGeneratedResources(resources ...ResourceSpec) { + newResources := make([]ResourceSpec, 0) + for _, resource := range resources { + replaced := false + for i, r := range in.GeneratedResources { + if r.Name == resource.Name { + in.GeneratedResources[i] = resource + replaced = true + break + } + } + if !replaced { + newResources = append(newResources, resource) + } + } + + in.GeneratedResources = append(in.GeneratedResources, newResources...) +} + // Configurations -- func (in *IntegrationSpec) Configurations() []ConfigurationSpec { if in == nil { diff --git a/pkg/trait/prometheus.go b/pkg/trait/prometheus.go index f4898746b3..874829e5d8 100644 --- a/pkg/trait/prometheus.go +++ b/pkg/trait/prometheus.go @@ -19,24 +19,27 @@ package trait import ( "fmt" + "path" "strconv" - - v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/envvar" + "strings" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" + + "github.com/apache/camel-k/deploy" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/util" ) -// The Prometheus trait exposes the integration with a `Service` and a `ServiceMonitor` resources -// so that the Prometheus endpoint can be scraped. +// The Prometheus trait configures the Prometheus JMX exporter and exposes the integration with a `Service` +// and a `ServiceMonitor` resources so that the Prometheus endpoint can be scraped. // -// WARNING: Creating the `ServiceMonitor` resource requires the https://github.com/coreos/prometheus-operator[Prometheus Operator] -// custom resource definition to be installed. You can set `service-monitor` to `false` for the Prometheus trait to work without -// the Prometheus operator. +// WARNING: The creation of the `ServiceMonitor` resource requires the https://github.com/coreos/prometheus-operator[Prometheus Operator] +//custom resource definition to be installed. +// You can set `service-monitor` to `false` for the Prometheus trait to work without the Prometheus operator. // // It's disabled by default. // @@ -51,10 +54,12 @@ type prometheusTrait struct { ServiceMonitorLabels string `property:"service-monitor-labels"` } -const prometheusPortName = "prometheus" +const ( + prometheusJmxExporterConfigFileName = "prometheus-jmx-exporter.yaml" + prometheusJmxExporterConfigMountPath = "/etc/prometheus" + prometheusPortName = "prometheus" +) -// The Prometheus trait must be executed prior to the deployment trait -// as it mutates environment variables func newPrometheusTrait() *prometheusTrait { return &prometheusTrait{ BaseTrait: newBaseTrait("prometheus"), @@ -64,10 +69,35 @@ func newPrometheusTrait() *prometheusTrait { } func (t *prometheusTrait) Configure(e *Environment) (bool, error) { - return e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning), nil + return t.Enabled != nil && *t.Enabled && e.IntegrationInPhase( + v1.IntegrationPhaseInitialization, + v1.IntegrationPhaseDeploying, + v1.IntegrationPhaseRunning, + ), nil } func (t *prometheusTrait) Apply(e *Environment) (err error) { + if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + // Add the Camel management and Prometheus agent dependencies + util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel/camel-management") + // TODO: We may want to make the Prometheus version configurable + util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:io.prometheus.jmx/jmx_prometheus_javaagent:0.3.1") + + // Add the default Prometheus JMX exporter configuration + // TODO: Support user-provided configuration + configMap := t.getJmxExporterConfigMap(e) + e.Resources.Add(configMap) + e.Integration.Status.AddOrReplaceGeneratedResources(v1.ResourceSpec{ + Type: v1.ResourceTypeData, + DataSpec: v1.DataSpec{ + Name: prometheusJmxExporterConfigFileName, + ContentRef: configMap.Name, + }, + MountPath: prometheusJmxExporterConfigMountPath, + }) + return nil + } + container := e.getIntegrationContainer() if container == nil { e.Integration.Status.SetCondition( @@ -79,13 +109,6 @@ func (t *prometheusTrait) Apply(e *Environment) (err error) { return nil } - if t.Enabled == nil || !*t.Enabled { - // Deactivate the Prometheus Java agent - // Note: the AB_PROMETHEUS_OFF environment variable acts as an option flag - envvar.SetVal(&container.Env, "AB_PROMETHEUS_OFF", "true") - return nil - } - condition := v1.IntegrationCondition{ Type: v1.IntegrationConditionPrometheusAvailable, Status: corev1.ConditionTrue, @@ -93,7 +116,8 @@ func (t *prometheusTrait) Apply(e *Environment) (err error) { } // Configure the Prometheus Java agent - envvar.SetVal(&container.Env, "AB_PROMETHEUS_PORT", strconv.Itoa(t.Port)) + options := []string{strconv.Itoa(t.Port), path.Join(prometheusJmxExporterConfigMountPath, prometheusJmxExporterConfigFileName)} + container.Args = append(container.Args, "-javaagent:dependencies/io.prometheus.jmx.jmx_prometheus_javaagent-0.3.1.jar="+strings.Join(options, ":")) // Add the container port containerPort := t.getContainerPort() @@ -191,3 +215,22 @@ func (t *prometheusTrait) getServiceMonitorFor(e *Environment) (*monitoringv1.Se } return &smt, nil } + +func (t *prometheusTrait) getJmxExporterConfigMap(e *Environment) *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: e.Integration.Name + "-prometheus", + Namespace: e.Integration.Namespace, + Labels: map[string]string{ + "camel.apache.org/integration": e.Integration.Name, + }, + }, + Data: map[string]string{ + "content": deploy.Resources["prometheus-jmx-exporter.yaml"], + }, + } +} diff --git a/pkg/trait/prometheus_test.go b/pkg/trait/prometheus_test.go index f5f7ab0071..144feb7da0 100644 --- a/pkg/trait/prometheus_test.go +++ b/pkg/trait/prometheus_test.go @@ -21,10 +21,6 @@ import ( "context" "testing" - v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/kubernetes" - "github.com/apache/camel-k/pkg/util/test" - "github.com/stretchr/testify/assert" monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" @@ -32,6 +28,9 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/util/kubernetes" ) func TestConfigurePrometheusTraitInRightPhaseDoesSucceed(t *testing.T) { @@ -62,7 +61,11 @@ func TestApplyNominalPrometheusTraitDoesSucceed(t *testing.T) { container := environment.Resources.GetContainerByName(defaultContainerName) assert.NotNil(t, container) - test.EnvVarHasValue(t, container.Env, "AB_PROMETHEUS_PORT", "9779") + + assert.Equal(t, container.Args, []string{ + "-javaagent:dependencies/io.prometheus.jmx.jmx_prometheus_javaagent-0.3.1.jar=9779:/etc/prometheus/prometheus-jmx-exporter.yaml", + }) + ports := container.Ports assert.Len(t, ports, 1) assert.Equal(t, "prometheus", ports[0].Name) @@ -147,19 +150,6 @@ func TestApplyPrometheusTraitWithServiceDoesNotSucceed(t *testing.T) { assert.Equal(t, corev1.ConditionFalse, condition.Status) } -func TestApplyDisabledPrometheusTraitShouldDeactivateJavaAgent(t *testing.T) { - trait, environment := createNominalPrometheusTest() - trait.Enabled = new(bool) - - err := trait.Apply(environment) - - assert.Nil(t, err) - - container := environment.Resources.GetContainerByName(defaultContainerName) - assert.NotNil(t, container) - test.EnvVarHasValue(t, container.Env, "AB_PROMETHEUS_OFF", "true") -} - func TestPrometheusTraitGetServiceMonitor(t *testing.T) { trait, environment := createNominalPrometheusTest()