From 83d8e0344fea845809d63a1670de66881922fa1f Mon Sep 17 00:00:00 2001 From: lburgazzoli Date: Tue, 12 Mar 2019 03:12:51 +0100 Subject: [PATCH] fix: include mount paths in java's classpath --- pkg/trait/builder_test.go | 3 +++ pkg/trait/classpath.go | 27 +++++++++++++-------------- pkg/trait/deployment.go | 22 ++++++++++++++++++++-- pkg/trait/environment_test.go | 23 ++++++++++++++++++++--- pkg/trait/knative_service.go | 23 ++++++++++++++++++----- pkg/trait/knative_service_env_test.go | 20 ++++++++++++++++++++ pkg/trait/knative_service_vol_test.go | 16 ++++++++++++++++ pkg/trait/trait_test.go | 12 ++++++++++-- pkg/trait/trait_types.go | 3 +++ pkg/util/test/assertions.go | 6 ++++++ 10 files changed, 129 insertions(+), 26 deletions(-) diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go index 50ecac7437..f37ba9a4df 100644 --- a/pkg/trait/builder_test.go +++ b/pkg/trait/builder_test.go @@ -21,6 +21,8 @@ import ( "context" "testing" + "github.com/scylladb/go-set/strset" + "github.com/apache/camel-k/pkg/util/defaults" "github.com/apache/camel-k/pkg/util/test" @@ -154,6 +156,7 @@ func createBuilderTestEnv(cluster v1alpha1.IntegrationPlatformCluster, strategy EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } } diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index 0ffcaab780..fd621b9362 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -19,12 +19,13 @@ package trait import ( "fmt" - "strings" - "github.com/pkg/errors" + "github.com/scylladb/go-set/strset" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" - "github.com/apache/camel-k/pkg/util/envvar" + + "github.com/pkg/errors" + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -42,11 +43,8 @@ func (t *classpathTrait) Configure(e *Environment) (bool, error) { if t.Enabled != nil && !*t.Enabled { return false, nil } - if e.InPhase(v1alpha1.IntegrationContextPhaseReady, v1alpha1.IntegrationPhaseDeploying) { - return true, nil - } - return false, nil + return e.InPhase(v1alpha1.IntegrationContextPhaseReady, v1alpha1.IntegrationPhaseDeploying), nil } func (t *classpathTrait) Apply(e *Environment) error { @@ -71,12 +69,15 @@ func (t *classpathTrait) Apply(e *Environment) error { return fmt.Errorf("unable to find integration context %s", e.Integration.Status.Context) } - deps := make([]string, 0, 2+len(ctx.Status.Artifacts)) - deps = append(deps, "/etc/camel/resources") - deps = append(deps, "./resources") + if e.Classpath == nil { + e.Classpath = strset.New() + } + + e.Classpath.Add("/etc/camel/resources") + e.Classpath.Add("./resources") for _, artifact := range ctx.Status.Artifacts { - deps = append(deps, artifact.Target) + e.Classpath.Add(artifact.Target) } if e.IntegrationContext.Labels["camel.apache.org/context.type"] == v1alpha1.IntegrationContextTypeExternal { @@ -85,10 +86,8 @@ func (t *classpathTrait) Apply(e *Environment) error { // the classpath so we assume the all jars in /deployments/dependencies/ have // to be taken into account // - deps = append(deps, "/deployments/dependencies/*") + e.Classpath.Add("/deployments/dependencies/*") } - envvar.SetVal(&e.EnvVars, "JAVA_CLASSPATH", strings.Join(deps, ":")) - return nil } diff --git a/pkg/trait/deployment.go b/pkg/trait/deployment.go index 7aebbee19c..6b580a9292 100644 --- a/pkg/trait/deployment.go +++ b/pkg/trait/deployment.go @@ -18,11 +18,11 @@ limitations under the License. package trait import ( + "sort" "strings" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/envvar" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -82,9 +82,11 @@ func (t *deploymentTrait) Apply(e *Environment) error { // trigger integration deploy e.Integration.Status.Phase = v1alpha1.IntegrationPhaseDeploying } + + return nil } - if e.Integration != nil && e.Integration.Status.Phase == v1alpha1.IntegrationPhaseDeploying { + if e.InPhase(v1alpha1.IntegrationContextPhaseReady, v1alpha1.IntegrationPhaseDeploying) { e.Resources.AddAll(e.ComputeConfigMaps(t.deployer.ContainerImage)) e.Resources.Add(t.getDeploymentFor(e)) } @@ -178,5 +180,21 @@ func (t *deploymentTrait) getDeploymentFor(e *Environment) *appsv1.Deployment { &deployment.Spec.Template.Spec.Containers[0].VolumeMounts, ) + // + // Add mounted volumes as resources + // + for _, c := range deployment.Spec.Template.Spec.Containers { + for _, m := range c.VolumeMounts { + e.Classpath.Add(m.MountPath) + } + } + + cp := e.Classpath.List() + + // keep classpath sorted + sort.Strings(cp) + + envvar.SetVal(&deployment.Spec.Template.Spec.Containers[0].Env, "JAVA_CLASSPATH", strings.Join(cp, ":")) + return &deployment } diff --git a/pkg/trait/environment_test.go b/pkg/trait/environment_test.go index 8e3340f4e9..c210105c9e 100644 --- a/pkg/trait/environment_test.go +++ b/pkg/trait/environment_test.go @@ -21,6 +21,8 @@ import ( "context" "testing" + "github.com/scylladb/go-set/strset" + "github.com/apache/camel-k/pkg/util/test" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" @@ -46,7 +48,11 @@ func TestDefaultEnvironment(t *testing.T) { Profile: v1alpha1.TraitProfileOpenShift, }, }, - IntegrationContext: &v1alpha1.IntegrationContext{}, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -55,6 +61,7 @@ func TestDefaultEnvironment(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = NewEnvironmentTestCatalog().apply(&env) @@ -106,7 +113,11 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) { }, }, }, - IntegrationContext: &v1alpha1.IntegrationContext{}, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -115,6 +126,7 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = NewEnvironmentTestCatalog().apply(&env) @@ -166,7 +178,11 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) { }, }, }, - IntegrationContext: &v1alpha1.IntegrationContext{}, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -175,6 +191,7 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = NewEnvironmentTestCatalog().apply(&env) diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go index 7e0bd44ece..4055c53c0f 100644 --- a/pkg/trait/knative_service.go +++ b/pkg/trait/knative_service.go @@ -18,7 +18,9 @@ limitations under the License. package trait import ( + "sort" "strconv" + "strings" "github.com/apache/camel-k/pkg/util/kubernetes" @@ -62,7 +64,7 @@ func (t *knativeServiceTrait) Configure(e *Environment) (bool, error) { return false, nil } - if !e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) { + if !e.InPhase(v1alpha1.IntegrationContextPhaseReady, v1alpha1.IntegrationPhaseDeploying) { return false, nil } @@ -203,10 +205,8 @@ func (t *knativeServiceTrait) getServiceFor(e *Environment) (*serving.Service, e if t.ConfigurationType == "volume" { t.bindToVolumes(e, &svc) - } else { - if err := t.bindToEnvVar(e, &svc); err != nil { - return nil, err - } + } else if err := t.bindToEnvVar(e, &svc); err != nil { + return nil, err } // add env vars from traits @@ -214,5 +214,18 @@ func (t *knativeServiceTrait) getServiceFor(e *Environment) (*serving.Service, e envvar.SetVar(&svc.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.Env, envVar) } + // Add mounted volumes as resources + for _, m := range svc.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.VolumeMounts { + e.Classpath.Add(m.MountPath) + } + + cp := e.Classpath.List() + + // keep classpath sorted + sort.Strings(cp) + + // set the classpath + envvar.SetVal(environment, "JAVA_CLASSPATH", strings.Join(cp, ":")) + return &svc, nil } diff --git a/pkg/trait/knative_service_env_test.go b/pkg/trait/knative_service_env_test.go index 0511739080..8396aa83d7 100644 --- a/pkg/trait/knative_service_env_test.go +++ b/pkg/trait/knative_service_env_test.go @@ -21,6 +21,8 @@ import ( "context" "testing" + "github.com/scylladb/go-set/strset" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/util/envvar" @@ -85,6 +87,11 @@ func TestKnativeTraitWithCompressedSources(t *testing.T) { }, }, }, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -97,6 +104,7 @@ func TestKnativeTraitWithCompressedSources(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = traitCatalog.apply(&environment) @@ -135,6 +143,9 @@ func TestKnativeTraitWithCompressedSources(t *testing.T) { resource = util.LookupEnvVar(vars, "CAMEL_K_RESOURCE_001") assert.NotNil(t, resource) assert.Equal(t, content, resource.Value) + + resource = util.LookupEnvVar(vars, "JAVA_CLASSPATH") + assert.NotNil(t, resource) }) assert.True(t, services > 0) @@ -174,6 +185,11 @@ func TestKnativeTraitWithConfigMapSources(t *testing.T) { }, }, }, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -198,6 +214,7 @@ func TestKnativeTraitWithConfigMapSources(t *testing.T) { "content": content, }, }), + Classpath: strset.New(), } err = traitCatalog.apply(&environment) @@ -220,6 +237,9 @@ func TestKnativeTraitWithConfigMapSources(t *testing.T) { route := util.LookupEnvVar(vars, "CAMEL_K_ROUTE_000") assert.NotNil(t, route) assert.Equal(t, content, route.Value) + + resource := util.LookupEnvVar(vars, "JAVA_CLASSPATH") + assert.NotNil(t, resource) }) assert.True(t, services > 0) diff --git a/pkg/trait/knative_service_vol_test.go b/pkg/trait/knative_service_vol_test.go index 8bdfe6c32f..87c860099f 100644 --- a/pkg/trait/knative_service_vol_test.go +++ b/pkg/trait/knative_service_vol_test.go @@ -21,6 +21,8 @@ import ( "context" "testing" + "github.com/scylladb/go-set/strset" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/envvar" "github.com/apache/camel-k/pkg/util/kubernetes" @@ -86,6 +88,11 @@ func TestKnativeWithVolumeBinding(t *testing.T) { }, }, }, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -98,6 +105,7 @@ func TestKnativeWithVolumeBinding(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = traitCatalog.apply(&environment) @@ -160,6 +168,7 @@ func TestKnativeWithVolumeBinding(t *testing.T) { } }) + test.EnvVarExists(t, spec.Container.Env, "JAVA_CLASSPATH") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_ROUTES", "file:/etc/camel/sources/i-source-000/routes.js?language=js&compression=true") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d") @@ -222,6 +231,11 @@ func TestKnativeWithVolumeBindingAndContainerImage(t *testing.T) { }, }, }, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: v1alpha1.IntegrationPlatformClusterOpenShift, @@ -234,6 +248,7 @@ func TestKnativeWithVolumeBindingAndContainerImage(t *testing.T) { EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } err = traitCatalog.apply(&environment) @@ -266,6 +281,7 @@ func TestKnativeWithVolumeBindingAndContainerImage(t *testing.T) { test.HasVolume(t, spec.Volumes, "my-secret") test.HasVolume(t, spec.Volumes, "integration-properties") + test.EnvVarExists(t, spec.Container.Env, "JAVA_CLASSPATH") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_ROUTES", "file:/deployments/sources/routes.js?language=js&compression=true") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties") test.EnvVarHasValue(t, spec.Container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d") diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go index 5d1d3da30d..31a80d9a92 100644 --- a/pkg/trait/trait_test.go +++ b/pkg/trait/trait_test.go @@ -21,12 +21,15 @@ import ( "context" "testing" - "github.com/apache/camel-k/pkg/util/test" + "github.com/scylladb/go-set/strset" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/kubernetes" + "github.com/apache/camel-k/pkg/util/test" + routev1 "github.com/openshift/api/route/v1" "github.com/stretchr/testify/assert" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -196,7 +199,11 @@ func createTestEnv(t *testing.T, cluster v1alpha1.IntegrationPlatformCluster, sc Phase: v1alpha1.IntegrationPhaseDeploying, }, }, - IntegrationContext: &v1alpha1.IntegrationContext{}, + IntegrationContext: &v1alpha1.IntegrationContext{ + Status: v1alpha1.IntegrationContextStatus{ + Phase: v1alpha1.IntegrationContextPhaseReady, + }, + }, Platform: &v1alpha1.IntegrationPlatform{ Spec: v1alpha1.IntegrationPlatformSpec{ Cluster: cluster, @@ -205,6 +212,7 @@ func createTestEnv(t *testing.T, cluster v1alpha1.IntegrationPlatformCluster, sc EnvVars: make([]corev1.EnvVar, 0), ExecutedTraits: make([]Trait, 0), Resources: kubernetes.NewCollection(), + Classpath: strset.New(), } } diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index ddfb96dc5c..106f38abe6 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -24,6 +24,8 @@ import ( "strconv" "strings" + "github.com/scylladb/go-set/strset" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -114,6 +116,7 @@ type Environment struct { BuildDir string 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 diff --git a/pkg/util/test/assertions.go b/pkg/util/test/assertions.go index 52c8a9f3e3..4df8f9c2ee 100644 --- a/pkg/util/test/assertions.go +++ b/pkg/util/test/assertions.go @@ -26,6 +26,12 @@ import ( corev1 "k8s.io/api/core/v1" ) +// EnvVarExists -- +func EnvVarExists(t *testing.T, env []corev1.EnvVar, name string) { + ev := envvar.Get(env, name) + assert.NotNil(t, ev) +} + // EnvVarHasValue -- func EnvVarHasValue(t *testing.T, env []corev1.EnvVar, name string, val string) { ev := envvar.Get(env, name)