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

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

commit cc40921ab71f3283aed2fbbc22c0bed0451972c5
Author: lburgazzoli <lburgazz...@gmail.com>
AuthorDate: Mon Dec 17 18:37:22 2018 +0100

    add resources to an integration #241
---
 examples/resources-data.txt                      |   1 +
 examples/resources-route.groovy                  |  11 +++
 pkg/apis/camel/v1alpha1/types.go                 |  26 ++++--
 pkg/apis/camel/v1alpha1/types_support.go         |  21 +++++
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |  39 +++++++++
 pkg/builder/builder.go                           |  11 ++-
 pkg/builder/builder_steps.go                     |  20 ++---
 pkg/builder/builder_types.go                     |   3 +-
 pkg/builder/springboot/initializer.go            |  16 +++-
 pkg/client/cmd/run.go                            |  73 ++++++++++------
 pkg/metadata/metadata_dependencies_test.go       |  78 ++++++++++-------
 pkg/metadata/metadata_http_test.go               | 101 +++++++++++++++--------
 pkg/metadata/metadata_languages_test.go          |   8 +-
 pkg/metadata/metadata_uri_test.go                |  57 ++++++++-----
 pkg/stub/action/integration/build_image.go       |   6 ++
 pkg/stub/action/integration/deploy.go            |  13 ++-
 pkg/trait/catalog.go                             |  12 ++-
 pkg/trait/classpath.go                           |  83 +++++++++++++++++++
 pkg/trait/deployment.go                          |  94 +++++++++++++++------
 pkg/trait/knative_test.go                        |  10 ++-
 pkg/trait/springboot.go                          |  44 +++++-----
 pkg/trait/trait_test.go                          |   6 +-
 pkg/util/digest/digest.go                        |   8 ++
 pkg/util/envvar/envvar.go                        |  11 +++
 24 files changed, 549 insertions(+), 203 deletions(-)

diff --git a/examples/resources-data.txt b/examples/resources-data.txt
new file mode 100644
index 0000000..dff7947
--- /dev/null
+++ b/examples/resources-data.txt
@@ -0,0 +1 @@
+the file body
\ No newline at end of file
diff --git a/examples/resources-route.groovy b/examples/resources-route.groovy
new file mode 100644
index 0000000..e87c930
--- /dev/null
+++ b/examples/resources-route.groovy
@@ -0,0 +1,11 @@
+//
+// To run this integrations use:
+//
+//     kamel run --resource examples/resources-data.txt 
examples/resources-route.groovy
+//
+
+from('timer:resources')
+    .routeId('resources')
+    .setBody()
+        .simple("resource:classpath:resources-data.txt")
+    .log('file content is: ${body}')
diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 8965778..0627da1 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -55,6 +55,7 @@ type Integration struct {
 type IntegrationSpec struct {
        Replicas      *int32                          
`json:"replicas,omitempty"`
        Sources       []SourceSpec                    `json:"sources,omitempty"`
+       Resources     []ResourceSpec                  
`json:"resources,omitempty"`
        Context       string                          `json:"context,omitempty"`
        Dependencies  []string                        
`json:"dependencies,omitempty"`
        Profile       TraitProfile                    `json:"profile,omitempty"`
@@ -65,7 +66,7 @@ type IntegrationSpec struct {
 
 // AddSource --
 func (is *IntegrationSpec) AddSource(name string, content string, language 
Language) {
-       is.Sources = append(is.Sources, SourceSpec{Name: name, Content: 
content, Language: language})
+       is.Sources = append(is.Sources, NewSourceSpec(name, content, language))
 }
 
 // AddSources --
@@ -73,6 +74,11 @@ func (is *IntegrationSpec) AddSources(sources ...SourceSpec) 
{
        is.Sources = append(is.Sources, sources...)
 }
 
+// AddResources --
+func (is *IntegrationSpec) AddResources(resources ...ResourceSpec) {
+       is.Resources = append(is.Resources, resources...)
+}
+
 // AddConfiguration --
 func (is *IntegrationSpec) AddConfiguration(confType string, confValue string) 
{
        is.Configuration = append(is.Configuration, ConfigurationSpec{
@@ -93,12 +99,22 @@ func (is *IntegrationSpec) AddDependency(dependency string) 
{
        }
 }
 
+// DataSpec --
+type DataSpec struct {
+       Name        string `json:"name,omitempty"`
+       Content     string `json:"content,omitempty"`
+       Compression bool   `json:"compression,omitempty"`
+}
+
+// ResourceSpec --
+type ResourceSpec struct {
+       DataSpec
+}
+
 // SourceSpec --
 type SourceSpec struct {
-       Name        string   `json:"name,omitempty"`
-       Content     string   `json:"content,omitempty"`
-       Language    Language `json:"language,omitempty"`
-       Compression bool     `json:"compression,omitempty"`
+       DataSpec
+       Language Language `json:"language,omitempty"`
 }
 
 // Language --
diff --git a/pkg/apis/camel/v1alpha1/types_support.go 
b/pkg/apis/camel/v1alpha1/types_support.go
index 1a9a9c4..21df605 100644
--- a/pkg/apis/camel/v1alpha1/types_support.go
+++ b/pkg/apis/camel/v1alpha1/types_support.go
@@ -40,6 +40,27 @@ func (spec ConfigurationSpec) String() string {
 //
 // **********************************
 
+// NewSourceSpec --
+func NewSourceSpec(name string, content string, language Language) SourceSpec {
+       return SourceSpec{
+               DataSpec: DataSpec{
+                       Name:    name,
+                       Content: content,
+               },
+               Language: language,
+       }
+}
+
+// NewResourceSpec --
+func NewResourceSpec(name string, content string, destination string) 
ResourceSpec {
+       return ResourceSpec{
+               DataSpec: DataSpec{
+                       Name:    name,
+                       Content: content,
+               },
+       }
+}
+
 // NewIntegrationPlatformList --
 func NewIntegrationPlatformList() IntegrationPlatformList {
        return IntegrationPlatformList{
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index fd37d68..c61ab94 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -58,6 +58,22 @@ func (in *ConfigurationSpec) DeepCopy() *ConfigurationSpec {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *DataSpec) DeepCopyInto(out *DataSpec) {
+       *out = *in
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new DataSpec.
+func (in *DataSpec) DeepCopy() *DataSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(DataSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *Integration) DeepCopyInto(out *Integration) {
        *out = *in
        out.TypeMeta = in.TypeMeta
@@ -373,6 +389,11 @@ func (in *IntegrationSpec) DeepCopyInto(out 
*IntegrationSpec) {
                *out = make([]SourceSpec, len(*in))
                copy(*out, *in)
        }
+       if in.Resources != nil {
+               in, out := &in.Resources, &out.Resources
+               *out = make([]ResourceSpec, len(*in))
+               copy(*out, *in)
+       }
        if in.Dependencies != nil {
                in, out := &in.Dependencies, &out.Dependencies
                *out = make([]string, len(*in))
@@ -448,8 +469,26 @@ func (in *IntegrationTraitSpec) DeepCopy() 
*IntegrationTraitSpec {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) {
+       *out = *in
+       out.DataSpec = in.DataSpec
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ResourceSpec.
+func (in *ResourceSpec) DeepCopy() *ResourceSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(ResourceSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
        *out = *in
+       out.DataSpec = in.DataSpec
        return
 }
 
diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go
index ffe9f92..58d814e 100644
--- a/pkg/builder/builder.go
+++ b/pkg/builder/builder.go
@@ -143,12 +143,11 @@ func (b *defaultBuilder) submit(request Request) {
        b.request.Store(request.Meta.Name, r)
 
        c := Context{
-               C:                b.ctx,
-               Path:             builderPath,
-               Namespace:        b.namespace,
-               Request:          request,
-               ComputeClasspath: true,
-               Image:            "fabric8/s2i-java:2.3", // TODO: externalize
+               C:         b.ctx,
+               Path:      builderPath,
+               Namespace: b.namespace,
+               Request:   request,
+               Image:     "fabric8/s2i-java:2.3", // TODO: externalize,
        }
 
        if request.Image != "" {
diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go
index 91035e0..8799d58 100644
--- a/pkg/builder/builder_steps.go
+++ b/pkg/builder/builder_steps.go
@@ -166,7 +166,7 @@ func IncrementalPackager(ctx *Context) error {
                return StandardPackager(ctx)
        }
 
-       images, err := ListPublishedImages(ctx.Namespace)
+       images, err := ListPublishedImages(ctx)
        if err != nil {
                return err
        }
@@ -228,27 +228,16 @@ func packager(ctx *Context, selector ArtifactsSelector) 
error {
                }
        }
 
-       if ctx.ComputeClasspath && len(ctx.Artifacts) > 0 {
-               cp := ""
-               for _, entry := range ctx.Artifacts {
-                       cp += entry.Target + "\n"
-               }
-
-               if err := tarAppender.AddData([]byte(cp), "classpath"); err != 
nil {
-                       return err
-               }
-       }
-
        ctx.Archive = tarFileName
 
        return nil
 }
 
 // ListPublishedImages --
-func ListPublishedImages(namespace string) ([]PublishedImage, error) {
+func ListPublishedImages(context *Context) ([]PublishedImage, error) {
        list := v1alpha1.NewIntegrationContextList()
 
-       err := sdk.List(namespace, &list, 
sdk.WithListOptions(&metav1.ListOptions{}))
+       err := sdk.List(context.Namespace, &list, 
sdk.WithListOptions(&metav1.ListOptions{}))
        if err != nil {
                return nil, err
        }
@@ -257,6 +246,9 @@ func ListPublishedImages(namespace string) 
([]PublishedImage, error) {
                if ctx.Status.Phase != v1alpha1.IntegrationContextPhaseReady || 
ctx.Labels == nil {
                        continue
                }
+               if context.ContextFiler != nil && !context.ContextFiler(&ctx) {
+                       continue
+               }
                if ctxType, present := 
ctx.Labels["camel.apache.org/context.type"]; !present || ctxType != 
v1alpha1.IntegrationContextTypePlatform {
                        continue
                }
diff --git a/pkg/builder/builder_types.go b/pkg/builder/builder_types.go
index 54f9774..89e2e86 100644
--- a/pkg/builder/builder_types.go
+++ b/pkg/builder/builder_types.go
@@ -147,8 +147,7 @@ type Context struct {
        Artifacts         []v1alpha1.Artifact
        SelectedArtifacts []v1alpha1.Artifact
        Archive           string
-       ComputeClasspath  bool
-       MainClass         string
+       ContextFiler      func(integrationContext *v1alpha1.IntegrationContext) 
bool
 }
 
 // HasRequiredImage --
diff --git a/pkg/builder/springboot/initializer.go 
b/pkg/builder/springboot/initializer.go
index 2b8b5af..1add06e 100644
--- a/pkg/builder/springboot/initializer.go
+++ b/pkg/builder/springboot/initializer.go
@@ -18,14 +18,24 @@ limitations under the License.
 package springboot
 
 import (
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
        "github.com/apache/camel-k/pkg/builder"
 )
 
 // Initialize --
 func Initialize(ctx *builder.Context) error {
-       // no need to compute classpath as we do use spring boot own
-       // loader: PropertiesLauncher
-       ctx.ComputeClasspath = false
+       // do not take into account any image that does not have spring-boot
+       // as required dependency to avoid picking up a base image with wrong
+       // classpath or layout
+       ctx.ContextFiler = func(context *v1alpha1.IntegrationContext) bool {
+               for _, i := range context.Spec.Dependencies {
+                       if i == "runtime:spring" {
+                               return true
+                       }
+               }
+
+               return false
+       }
 
        return nil
 }
diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go
index de784b9..376b91a 100644
--- a/pkg/client/cmd/run.go
+++ b/pkg/client/cmd/run.go
@@ -85,6 +85,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command 
{
                "E.g. \"--logging-level org.apache.camel=DEBUG\"")
        cmd.Flags().StringVarP(&options.OutputFormat, "output", "o", "", 
"Output format. One of: json|yaml")
        cmd.Flags().BoolVar(&options.Compression, "compression", false, "Enable 
store source as a compressed binary blob")
+       cmd.Flags().StringSliceVar(&options.Resources, "resource", nil, "Add a 
resource")
 
        // completion support
        configureKnownCompletions(&cmd)
@@ -104,6 +105,7 @@ type runCmdOptions struct {
        IntegrationName    string
        Profile            string
        OutputFormat       string
+       Resources          []string
        Dependencies       []string
        Properties         []string
        ConfigMaps         []string
@@ -247,8 +249,8 @@ func (o *runCmdOptions) syncIntegration(sources []string) 
error {
        return nil
 }
 
-func (o *runCmdOptions) createIntegration(args []string) 
(*v1alpha1.Integration, error) {
-       return o.updateIntegrationCode(args)
+func (o *runCmdOptions) createIntegration(sources []string) 
(*v1alpha1.Integration, error) {
+       return o.updateIntegrationCode(sources)
 }
 
 func (o *runCmdOptions) updateIntegrationCode(sources []string) 
(*v1alpha1.Integration, error) {
@@ -285,25 +287,32 @@ func (o *runCmdOptions) updateIntegrationCode(sources 
[]string) (*v1alpha1.Integ
        }
 
        for _, source := range sources {
-               code, err := o.loadCode(source)
+               data, err := o.loadData(source, o.Compression)
                if err != nil {
                        return nil, err
                }
 
-               if o.Compression {
-                       var b bytes.Buffer
-
-                       if err := gzip.Compress(&b, []byte(code)); err != nil {
-                               return nil, err
-                       }
+               integration.Spec.AddSources(v1alpha1.SourceSpec{
+                       DataSpec: v1alpha1.DataSpec{
+                               Name:        path.Base(source),
+                               Content:     data,
+                               Compression: o.Compression,
+                       },
+               })
+       }
 
-                       code = base64.StdEncoding.EncodeToString(b.Bytes())
+       for _, resource := range o.Resources {
+               data, err := o.loadData(resource, o.Compression)
+               if err != nil {
+                       return nil, err
                }
 
-               integration.Spec.AddSources(v1alpha1.SourceSpec{
-                       Name:        path.Base(source),
-                       Content:     code,
-                       Compression: o.Compression,
+               integration.Spec.AddResources(v1alpha1.ResourceSpec{
+                       DataSpec: v1alpha1.DataSpec{
+                               Name:        path.Base(resource),
+                               Content:     data,
+                               Compression: o.Compression,
+                       },
                })
        }
 
@@ -381,23 +390,39 @@ func (o *runCmdOptions) updateIntegrationCode(sources 
[]string) (*v1alpha1.Integ
        return &integration, nil
 }
 
-func (*runCmdOptions) loadCode(fileName string) (string, error) {
+func (*runCmdOptions) loadData(fileName string, compress bool) (string, error) 
{
+       var content []byte
+       var err error
+
        if !strings.HasPrefix(fileName, "http://";) && 
!strings.HasPrefix(fileName, "https://";) {
-               content, err := ioutil.ReadFile(fileName)
+               content, err = ioutil.ReadFile(fileName)
+               if err != nil {
+                       return "", err
+               }
+       } else {
+               resp, err := http.Get(fileName)
+               if err != nil {
+                       return "", err
+               }
+               defer resp.Body.Close()
+
+               content, err = ioutil.ReadAll(resp.Body)
                if err != nil {
                        return "", err
                }
-               return string(content), nil
        }
 
-       resp, err := http.Get(fileName)
-       if err != nil {
-               return "", err
+       if compress {
+               var b bytes.Buffer
+
+               if err := gzip.Compress(&b, content); err != nil {
+                       return "", err
+               }
+
+               return base64.StdEncoding.EncodeToString(b.Bytes()), nil
        }
-       defer resp.Body.Close()
-       bodyBytes, err := ioutil.ReadAll(resp.Body)
-       bodyString := string(bodyBytes)
-       return bodyString, err
+
+       return string(content), nil
 }
 
 func (*runCmdOptions) configureTrait(integration *v1alpha1.Integration, config 
string) error {
diff --git a/pkg/metadata/metadata_dependencies_test.go 
b/pkg/metadata/metadata_dependencies_test.go
index 8eea487..9f952f5 100644
--- a/pkg/metadata/metadata_dependencies_test.go
+++ b/pkg/metadata/metadata_dependencies_test.go
@@ -26,14 +26,17 @@ import (
 
 func TestDependenciesJavaSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
+                           from("telegram:bots/cippa").to("log:stash");
+                           from("timer:tick").to("amqp:queue");
+                           from("ine:xistent").to("amqp:queue");
+                       `,
+               },
                Language: v1alpha1.LanguageJavaSource,
-               Content: `
-                       from("telegram:bots/cippa").to("log:stash");
-                       from("timer:tick").to("amqp:queue");
-                       from("ine:xistent").to("amqp:queue");
-               `,
        }
+
        meta := Extract(code)
        // assert all dependencies are found and sorted (removing duplicates)
        assert.Equal(t, []string{"camel:amqp", "camel:core", "camel:telegram"}, 
meta.Dependencies)
@@ -41,28 +44,33 @@ func TestDependenciesJavaSource(t *testing.T) {
 
 func TestDependenciesJavaClass(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.class",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.class",
+                       Content: `
+                           from("telegram:bots/cippa").to("log:stash");
+                           from("timer:tick").to("amqp:queue");
+                           from("ine:xistent").to("amqp:queue");
+                   `,
+               },
                Language: v1alpha1.LanguageJavaClass,
-               Content: `
-                       from("telegram:bots/cippa").to("log:stash");
-                       from("timer:tick").to("amqp:queue");
-                       from("ine:xistent").to("amqp:queue");
-               `,
        }
+
        meta := Extract(code)
        assert.Empty(t, meta.Dependencies)
 }
 
 func TestDependenciesJavaScript(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "source.js",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "source.js",
+                       Content: `
+                           from('telegram:bots/cippa').to("log:stash");
+                           from('timer:tick').to("amqp:queue");
+                           from("ine:xistent").to("amqp:queue");
+                           '"'
+                   `,
+               },
                Language: v1alpha1.LanguageJavaScript,
-               Content: `
-                       from('telegram:bots/cippa').to("log:stash");
-                       from('timer:tick').to("amqp:queue");
-                       from("ine:xistent").to("amqp:queue");
-                       '"'
-               `,
        }
        meta := Extract(code)
        // assert all dependencies are found and sorted (removing duplicates)
@@ -71,15 +79,18 @@ func TestDependenciesJavaScript(t *testing.T) {
 
 func TestDependenciesGroovy(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "source.groovy",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "source.groovy",
+                       Content: `
+                           from('telegram:bots/cippa').to("log:stash");
+                           from('timer:tick').to("amqp:queue");
+                           from("ine:xistent").to("amqp:queue");
+                           '"'
+                   `,
+               },
                Language: v1alpha1.LanguageGroovy,
-               Content: `
-                       from('telegram:bots/cippa').to("log:stash");
-                       from('timer:tick').to("amqp:queue");
-                       from("ine:xistent").to("amqp:queue");
-                       '"'
-               `,
        }
+
        meta := Extract(code)
        // assert all dependencies are found and sorted (removing duplicates)
        assert.Equal(t, []string{"camel:amqp", "camel:core", "camel:telegram"}, 
meta.Dependencies)
@@ -87,14 +98,17 @@ func TestDependenciesGroovy(t *testing.T) {
 
 func TestDependencies(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
+                           from("http4:test").to("log:end");
+                           from("https4:test").to("log:end");
+                           from("twitter-timeline:test").to("mock:end");
+                   `,
+               },
                Language: v1alpha1.LanguageJavaSource,
-               Content: `
-                       from("http4:test").to("log:end");
-                       from("https4:test").to("log:end");
-                       from("twitter-timeline:test").to("mock:end");
-               `,
        }
+
        meta := Extract(code)
        // assert all dependencies are found and sorted (removing duplicates)
        assert.Equal(t, []string{"camel:core", "camel:http4", "camel:twitter"}, 
meta.Dependencies)
diff --git a/pkg/metadata/metadata_http_test.go 
b/pkg/metadata/metadata_http_test.go
index 59cc1cd..adc5cdd 100644
--- a/pkg/metadata/metadata_http_test.go
+++ b/pkg/metadata/metadata_http_test.go
@@ -26,13 +26,15 @@ import (
 
 func TestHttpJavaSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
                        from("telegram:bots/cippa").to("log:stash");
                        from("undertow:uri").to("log:stash");
                        from("ine:xistent").to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -41,13 +43,16 @@ func TestHttpJavaSource(t *testing.T) {
 
 func TestHttpOnlyJavaSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
                        from("direct:bots/cippa").to("log:stash");
                        from("undertow:uri").to("log:stash");
                        from("seda:path").to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -56,12 +61,14 @@ func TestHttpOnlyJavaSource(t *testing.T) {
 
 func TestHttpOnlyJavaSourceRest(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
                        from("direct:bots/cippa").to("log:stash");
                        rest().get("").to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -70,12 +77,14 @@ func TestHttpOnlyJavaSourceRest(t *testing.T) {
 
 func TestHttpOnlyJavaSourceRest2(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+                       Content: `
                        from("vm:bots/cippa").to("log:stash");
                        rest( ).get("").to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -84,13 +93,15 @@ func TestHttpOnlyJavaSourceRest2(t *testing.T) {
 
 func TestNoHttpGroovySource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.groovy",
-               Language: v1alpha1.LanguageGroovy,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.groovy",
+                       Content: `
                        from('direct:bots/cippa').to("log:stash");
                        from('teelgram:uri').to("log:stash");
                        from('seda:path').to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageGroovy,
        }
        meta := Extract(code)
        assert.False(t, meta.RequiresHTTPService)
@@ -99,13 +110,15 @@ func TestNoHttpGroovySource(t *testing.T) {
 
 func TestHttpOnlyGroovySource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.groovy",
-               Language: v1alpha1.LanguageGroovy,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.groovy",
+                       Content: `
                        from('direct:bots/cippa').to("log:stash");
                        from('undertow:uri').to("log:stash");
                        from('seda:path').to("log:stash");
                `,
+               },
+               Language: v1alpha1.LanguageGroovy,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -114,13 +127,15 @@ func TestHttpOnlyGroovySource(t *testing.T) {
 
 func TestHttpXMLSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "routes.xml",
-               Language: v1alpha1.LanguageXML,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "routes.xml",
+                       Content: `
                        <from uri="telegram:ciao" />
                        <rest path="/">
                        </rest>
                `,
+               },
+               Language: v1alpha1.LanguageXML,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -129,13 +144,16 @@ func TestHttpXMLSource(t *testing.T) {
 
 func TestHttpOnlyXMLSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "routes.xml",
-               Language: v1alpha1.LanguageXML,
-               Content: `
+
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "routes.xml",
+                       Content: `
                        <from uri="direct:ciao" />
                        <rest path="/">
                        </rest>
                `,
+               },
+               Language: v1alpha1.LanguageXML,
        }
        meta := Extract(code)
        assert.True(t, meta.RequiresHTTPService)
@@ -145,20 +163,25 @@ func TestHttpOnlyXMLSource(t *testing.T) {
 func TestMultilangHTTPOnlySource(t *testing.T) {
        codes := []v1alpha1.SourceSpec{
                {
-                       Name:     "routes.xml",
-                       Language: v1alpha1.LanguageXML,
-                       Content: `
+                       DataSpec: v1alpha1.DataSpec{
+                               Name: "routes.xml",
+                               Content: `
                                <from uri="direct:ciao" />
                                <rest path="/">
                                </rest>
                        `,
+                       },
+                       Language: v1alpha1.LanguageXML,
                },
                {
-                       Name:     "routes2.groovy",
-                       Language: v1alpha1.LanguageGroovy,
-                       Content: `
+
+                       DataSpec: v1alpha1.DataSpec{
+                               Name: "routes2.groovy",
+                               Content: `
                                from('seda:in').to('seda:out')
                        `,
+                       },
+                       Language: v1alpha1.LanguageGroovy,
                },
        }
        meta := ExtractAll(codes)
@@ -169,21 +192,27 @@ func TestMultilangHTTPOnlySource(t *testing.T) {
 func TestMultilangHTTPSource(t *testing.T) {
        codes := []v1alpha1.SourceSpec{
                {
-                       Name:     "routes.xml",
-                       Language: v1alpha1.LanguageXML,
-                       Content: `
+
+                       DataSpec: v1alpha1.DataSpec{
+                               Name: "routes.xml",
+                               Content: `
                                <from uri="direct:ciao" />
                                <rest path="/">
                                </rest>
                        `,
+                       },
+                       Language: v1alpha1.LanguageXML,
                },
                {
-                       Name:     "routes2.groovy",
-                       Language: v1alpha1.LanguageGroovy,
-                       Content: `
+
+                       DataSpec: v1alpha1.DataSpec{
+                               Name: "routes2.groovy",
+                               Content: `
                                from('seda:in').to('seda:out')
                                from('timer:tick').to('log:info')
                        `,
+                       },
+                       Language: v1alpha1.LanguageGroovy,
                },
        }
        meta := ExtractAll(codes)
diff --git a/pkg/metadata/metadata_languages_test.go 
b/pkg/metadata/metadata_languages_test.go
index 5382d38..8a11a56 100644
--- a/pkg/metadata/metadata_languages_test.go
+++ b/pkg/metadata/metadata_languages_test.go
@@ -26,7 +26,9 @@ import (
 
 func TestLanguageJavaSource(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name: "Request.java",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+               },
        }
        meta := Extract(code)
        assert.Equal(t, v1alpha1.LanguageJavaSource, meta.Language)
@@ -34,7 +36,9 @@ func TestLanguageJavaSource(t *testing.T) {
 
 func TestLanguageAlreadySet(t *testing.T) {
        code := v1alpha1.SourceSpec{
-               Name:     "Request.java",
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "Request.java",
+               },
                Language: v1alpha1.LanguageJavaScript,
        }
        meta := Extract(code)
diff --git a/pkg/metadata/metadata_uri_test.go 
b/pkg/metadata/metadata_uri_test.go
index 1214ef6..9dc26d4 100644
--- a/pkg/metadata/metadata_uri_test.go
+++ b/pkg/metadata/metadata_uri_test.go
@@ -26,9 +26,9 @@ import (
 
 func TestJava1(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        import org.apache.camel.builder.RouteBuilder;
 
                        public class Sample extends RouteBuilder {
@@ -40,6 +40,8 @@ func TestJava1(t *testing.T) {
                                }
                        }
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
 
        metadata := Extract(source)
@@ -51,9 +53,9 @@ func TestJava1(t *testing.T) {
 
 func TestJava2(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageJavaSource,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        import org.apache.camel.builder.RouteBuilder;
 
                        public class Sample extends RouteBuilder {
@@ -71,6 +73,8 @@ func TestJava2(t *testing.T) {
                                }
                        }
                `,
+               },
+               Language: v1alpha1.LanguageJavaSource,
        }
 
        metadata := Extract(source)
@@ -84,9 +88,9 @@ func TestJava2(t *testing.T) {
 
 func TestGroovy1(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageGroovy,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        
                        from( "timer:tick")
                        .setBody().constant("aa")
@@ -97,6 +101,8 @@ func TestGroovy1(t *testing.T) {
                        .setBody().constant("aa")
                                .to('uri:3')
                `,
+               },
+               Language: v1alpha1.LanguageGroovy,
        }
 
        metadata := Extract(source)
@@ -111,10 +117,9 @@ func TestGroovy1(t *testing.T) {
 
 func TestGroovy2(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageGroovy,
-               Content: `
-                       
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `                      
                        rest().get("/")
                                .to   
('log:info?skipBodyLineSeparator=false').to( 'http://url' )
                                                .toD('dyn:1')
@@ -122,6 +127,8 @@ func TestGroovy2(t *testing.T) {
                                                .toD( "dyn:2")
                                                .toF( "f:%s", "2")
                `,
+               },
+               Language: v1alpha1.LanguageGroovy,
        }
 
        metadata := Extract(source)
@@ -136,9 +143,9 @@ func TestGroovy2(t *testing.T) {
 
 func TestXml1(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageXML,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        <routes>
                            <route id="hello">
                                <from uri="timer:hello?period=3s"/>
@@ -151,6 +158,8 @@ func TestXml1(t *testing.T) {
                        </route>
                        </routes>
                `,
+               },
+               Language: v1alpha1.LanguageXML,
        }
 
        metadata := Extract(source)
@@ -164,9 +173,9 @@ func TestXml1(t *testing.T) {
 
 func TestKotlin1(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageKotlin,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        
                        from( "timer:tick")
                        .setBody().constant("aa")
@@ -179,6 +188,8 @@ func TestKotlin1(t *testing.T) {
                                .toD("uri:4")
                                .toF("uri:%s", 5)
                `,
+               },
+               Language: v1alpha1.LanguageKotlin,
        }
 
        metadata := Extract(source)
@@ -195,15 +206,17 @@ func TestKotlin1(t *testing.T) {
 
 func TestJavascript1(t *testing.T) {
        source := v1alpha1.SourceSpec{
-               Name:     "test",
-               Language: v1alpha1.LanguageJavaScript,
-               Content: `
+               DataSpec: v1alpha1.DataSpec{
+                       Name: "test",
+                       Content: `
                        
                        rest().get("/")
                                .to   
('log:info?skipBodyLineSeparator=false').to( 'http://url' )
                                .toD("uri:2")
                                .toF("uri:%s", "3") 
                `,
+               },
+               Language: v1alpha1.LanguageJavaScript,
        }
 
        metadata := Extract(source)
diff --git a/pkg/stub/action/integration/build_image.go 
b/pkg/stub/action/integration/build_image.go
index e23e6d0..44440cf 100644
--- a/pkg/stub/action/integration/build_image.go
+++ b/pkg/stub/action/integration/build_image.go
@@ -101,6 +101,12 @@ func (action *buildImageAction) Handle(integration 
*v1alpha1.Integration) error
                        Target:  path.Join("sources", source.Name),
                })
        }
+       for _, resource := range integration.Spec.Resources {
+               r.Resources = append(r.Resources, builder.Resource{
+                       Content: []byte(resource.Content),
+                       Target:  path.Join("resources", resource.Name),
+               })
+       }
 
        res := b.Submit(r)
 
diff --git a/pkg/stub/action/integration/deploy.go 
b/pkg/stub/action/integration/deploy.go
index 1ad22ab..ad0d04a 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -22,6 +22,7 @@ import (
        "github.com/apache/camel-k/pkg/trait"
        "github.com/apache/camel-k/pkg/util/kubernetes"
        "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/pkg/errors"
        "github.com/sirupsen/logrus"
 )
 
@@ -42,10 +43,18 @@ func (action *deployAction) CanHandle(integration 
*v1alpha1.Integration) bool {
 }
 
 func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
-       env, err := trait.Apply(integration, nil)
+       ctxName := integration.Spec.Context
+       ctx := v1alpha1.NewIntegrationContext(integration.Namespace, ctxName)
+
+       if err := sdk.Get(&ctx); err != nil {
+               return errors.Wrapf(err, "unable to find integration context 
%s, %s", ctxName, err)
+       }
+
+       env, err := trait.Apply(integration, &ctx)
        if err != nil {
                return err
        }
+
        // TODO we should look for objects that are no longer present in the 
collection and remove them
        err = kubernetes.ReplaceResources(env.Resources.Items())
        if err != nil {
@@ -53,8 +62,8 @@ func (action *deployAction) Handle(integration 
*v1alpha1.Integration) error {
        }
 
        target := integration.DeepCopy()
-       logrus.Info("Integration ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationPhaseRunning)
        target.Status.Phase = v1alpha1.IntegrationPhaseRunning
+       logrus.Info("Integration ", target.Name, " transitioning to state ", 
target.Status.Phase)
 
        return sdk.Update(target)
 }
diff --git a/pkg/trait/catalog.go b/pkg/trait/catalog.go
index 0fd5668..0e5b925 100644
--- a/pkg/trait/catalog.go
+++ b/pkg/trait/catalog.go
@@ -41,6 +41,7 @@ type Catalog struct {
        tSpringBoot   Trait
        tIstio        Trait
        tEnvironment  Trait
+       tClasspath    Trait
 }
 
 // NewCatalog creates a new trait Catalog
@@ -58,6 +59,7 @@ func NewCatalog() *Catalog {
                tSpringBoot:   newSpringBootTrait(),
                tIstio:        newIstioTrait(),
                tEnvironment:  newEnvironmentTrait(),
+               tClasspath:    newClasspathTrait(),
        }
 }
 
@@ -75,6 +77,7 @@ func (c *Catalog) allTraits() []Trait {
                c.tSpringBoot,
                c.tIstio,
                c.tEnvironment,
+               c.tClasspath,
        }
 }
 
@@ -85,8 +88,9 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait 
{
                        c.tDebug,
                        c.tDependencies,
                        c.tBuilder,
-                       c.tSpringBoot,
                        c.tEnvironment,
+                       c.tClasspath,
+                       c.tSpringBoot,
                        c.tDeployment,
                        c.tService,
                        c.tRoute,
@@ -97,8 +101,9 @@ func (c *Catalog) traitsFor(environment *Environment) 
[]Trait {
                        c.tDebug,
                        c.tDependencies,
                        c.tBuilder,
-                       c.tSpringBoot,
                        c.tEnvironment,
+                       c.tClasspath,
+                       c.tSpringBoot,
                        c.tDeployment,
                        c.tService,
                        c.tIngress,
@@ -109,8 +114,9 @@ func (c *Catalog) traitsFor(environment *Environment) 
[]Trait {
                        c.tDebug,
                        c.tDependencies,
                        c.tBuilder,
-                       c.tSpringBoot,
                        c.tEnvironment,
+                       c.tClasspath,
+                       c.tSpringBoot,
                        c.tKnative,
                        c.tDeployment,
                        c.tIstio,
diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go
new file mode 100644
index 0000000..3936584
--- /dev/null
+++ b/pkg/trait/classpath.go
@@ -0,0 +1,83 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+       "fmt"
+       "strings"
+
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/pkg/errors"
+
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/util/envvar"
+)
+
+type classpathTrait struct {
+       BaseTrait `property:",squash"`
+}
+
+func newClasspathTrait() *classpathTrait {
+       return &classpathTrait{
+               BaseTrait: BaseTrait{
+                       id: ID("classpath"),
+               },
+       }
+}
+
+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
+}
+
+func (t *classpathTrait) Apply(e *Environment) error {
+       ctx := e.Context
+
+       if ctx == nil && e.Integration.Spec.Context != "" {
+               name := e.Integration.Spec.Context
+               c := v1alpha1.NewIntegrationContext(e.Integration.Namespace, 
name)
+
+               if err := sdk.Get(&c); err != nil {
+                       return errors.Wrapf(err, "unable to find integration 
context %s, %s", name, err)
+               }
+
+               ctx = &c
+       }
+
+       if ctx == nil {
+               return fmt.Errorf("unable to find integration context %s", 
e.Integration.Spec.Context)
+       }
+
+       deps := make([]string, 0, 2+len(ctx.Status.Artifacts))
+       deps = append(deps, "/etc/camel/resources")
+       deps = append(deps, "./resources")
+
+       for _, artifact := range ctx.Status.Artifacts {
+               deps = append(deps, artifact.Target)
+       }
+
+       envvar.SetVal(&e.EnvVars, "JAVA_CLASSPATH", strings.Join(deps, ":"))
+
+       return nil
+}
diff --git a/pkg/trait/deployment.go b/pkg/trait/deployment.go
index 6b33485..ec53ac3 100644
--- a/pkg/trait/deployment.go
+++ b/pkg/trait/deployment.go
@@ -126,8 +126,9 @@ func (t *deploymentTrait) getConfigMapsFor(e *Environment) 
[]runtime.Object {
 
        if !t.ContainerImage {
 
-               // do not create 'source' ConfigMap if a docker images for 
deployment
+               // do not create 'source' or 'resource' ConfigMap if a docker 
images for deployment
                // is required
+
                for i, s := range e.Integration.Spec.Sources {
                        cm := corev1.ConfigMap{
                                TypeMeta: metav1.TypeMeta{
@@ -147,7 +148,32 @@ func (t *deploymentTrait) getConfigMapsFor(e *Environment) 
[]runtime.Object {
                                        },
                                },
                                Data: map[string]string{
-                                       "integration": s.Content,
+                                       "content": s.Content,
+                               },
+                       }
+
+                       maps = append(maps, &cm)
+               }
+
+               for i, s := range e.Integration.Spec.Resources {
+                       cm := corev1.ConfigMap{
+                               TypeMeta: metav1.TypeMeta{
+                                       Kind:       "ConfigMap",
+                                       APIVersion: "v1",
+                               },
+                               ObjectMeta: metav1.ObjectMeta{
+                                       Name:      
fmt.Sprintf("%s-resource-%03d", e.Integration.Name, i),
+                                       Namespace: e.Integration.Namespace,
+                                       Labels: map[string]string{
+                                               "camel.apache.org/integration": 
e.Integration.Name,
+                                       },
+                                       Annotations: map[string]string{
+                                               
"camel.apache.org/resource.name":        s.Name,
+                                               
"camel.apache.org/resource.compression": strconv.FormatBool(s.Compression),
+                                       },
+                               },
+                               Data: map[string]string{
+                                       "content": s.Content,
                                },
                        }
 
@@ -167,8 +193,8 @@ func (t *deploymentTrait) getConfigMapsFor(e *Environment) 
[]runtime.Object {
 func (t *deploymentTrait) getSources(e *Environment) []string {
        sources := make([]string, 0, len(e.Integration.Spec.Sources))
 
-       for i, s := range e.Integration.Spec.Sources {
-               root := fmt.Sprintf("/etc/camel/integrations/%03d", i)
+       for _, s := range e.Integration.Spec.Sources {
+               root := "/etc/camel/sources"
 
                if t.ContainerImage {
 
@@ -176,7 +202,8 @@ func (t *deploymentTrait) getSources(e *Environment) 
[]string {
                        root = "/deployments/sources"
                }
 
-               src := path.Join(root, s.Name)
+               srcName := strings.TrimPrefix(s.Name, "/")
+               src := path.Join(root, srcName)
                src = "file:" + src
 
                params := make([]string, 0)
@@ -272,7 +299,6 @@ func (t *deploymentTrait) getDeploymentFor(e *Environment) 
*appsv1.Deployment {
 
        vols := make([]corev1.Volume, 0)
        mnts := make([]corev1.VolumeMount, 0)
-       cnt := 0
 
        //
        // Volumes :: Properties
@@ -311,26 +337,48 @@ func (t *deploymentTrait) getDeploymentFor(e 
*Environment) *appsv1.Deployment {
                // do not need to mount any 'source' ConfigMap to the pod
 
                for i, s := range e.Integration.Spec.Sources {
+                       cmName := fmt.Sprintf("%s-source-%03d", 
e.Integration.Name, i)
+                       refName := fmt.Sprintf("integration-source-%03d", i)
+                       resName := strings.TrimPrefix(s.Name, "/")
+
                        vols = append(vols, corev1.Volume{
-                               Name: fmt.Sprintf("integration-source-%03d", i),
+                               Name: refName,
                                VolumeSource: corev1.VolumeSource{
                                        ConfigMap: 
&corev1.ConfigMapVolumeSource{
                                                LocalObjectReference: 
corev1.LocalObjectReference{
-                                                       Name: 
fmt.Sprintf("%s-source-%03d", e.Integration.Name, i),
+                                                       Name: cmName,
                                                },
-                                               Items: []corev1.KeyToPath{
-                                                       {
-                                                               Key:  
"integration",
-                                                               Path: 
strings.TrimPrefix(s.Name, "/"),
-                                                       },
+                                       },
+                               },
+                       })
+
+                       mnts = append(mnts, corev1.VolumeMount{
+                               Name:      refName,
+                               MountPath: path.Join("/etc/camel/sources", 
resName),
+                               SubPath:   "content",
+                       })
+               }
+
+               for i, r := range e.Integration.Spec.Resources {
+                       cmName := fmt.Sprintf("%s-resource-%03d", 
e.Integration.Name, i)
+                       refName := fmt.Sprintf("integration-resource-%03d", i)
+                       resName := strings.TrimPrefix(r.Name, "/")
+
+                       vols = append(vols, corev1.Volume{
+                               Name: refName,
+                               VolumeSource: corev1.VolumeSource{
+                                       ConfigMap: 
&corev1.ConfigMapVolumeSource{
+                                               LocalObjectReference: 
corev1.LocalObjectReference{
+                                                       Name: cmName,
                                                },
                                        },
                                },
                        })
 
                        mnts = append(mnts, corev1.VolumeMount{
-                               Name:      
fmt.Sprintf("integration-source-%03d", i),
-                               MountPath: 
fmt.Sprintf("/etc/camel/integrations/%03d", i),
+                               Name:      refName,
+                               MountPath: path.Join("/etc/camel/resources", 
resName),
+                               SubPath:   "content",
                        })
                }
        }
@@ -340,10 +388,10 @@ func (t *deploymentTrait) getDeploymentFor(e 
*Environment) *appsv1.Deployment {
        //
 
        VisitConfigurations("configmap", e.Context, e.Integration, func(cmName 
string) {
-               cnt++
+               refName := "integration-cm-" + strings.ToLower(cmName)
 
                vols = append(vols, corev1.Volume{
-                       Name: "integration-cm-" + cmName,
+                       Name: refName,
                        VolumeSource: corev1.VolumeSource{
                                ConfigMap: &corev1.ConfigMapVolumeSource{
                                        LocalObjectReference: 
corev1.LocalObjectReference{
@@ -354,8 +402,8 @@ func (t *deploymentTrait) getDeploymentFor(e *Environment) 
*appsv1.Deployment {
                })
 
                mnts = append(mnts, corev1.VolumeMount{
-                       Name:      "integration-cm-" + cmName,
-                       MountPath: fmt.Sprintf("/etc/camel/conf.d/%03d_%s", 
cnt, cmName),
+                       Name:      refName,
+                       MountPath: path.Join("/etc/camel/conf.d", refName),
                })
        })
 
@@ -364,10 +412,10 @@ func (t *deploymentTrait) getDeploymentFor(e 
*Environment) *appsv1.Deployment {
        //
 
        VisitConfigurations("secret", e.Context, e.Integration, func(secretName 
string) {
-               cnt++
+               refName := "integration-secret-" + strings.ToLower(secretName)
 
                vols = append(vols, corev1.Volume{
-                       Name: "integration-secret-" + secretName,
+                       Name: refName,
                        VolumeSource: corev1.VolumeSource{
                                Secret: &corev1.SecretVolumeSource{
                                        SecretName: secretName,
@@ -376,8 +424,8 @@ func (t *deploymentTrait) getDeploymentFor(e *Environment) 
*appsv1.Deployment {
                })
 
                mnts = append(mnts, corev1.VolumeMount{
-                       Name:      "integration-secret-" + secretName,
-                       MountPath: fmt.Sprintf("/etc/camel/conf.d/%03d_%s", 
cnt, secretName),
+                       Name:      refName,
+                       MountPath: path.Join("/etc/camel/conf.d", refName),
                })
        })
 
diff --git a/pkg/trait/knative_test.go b/pkg/trait/knative_test.go
index 4fd5c40..2d50e48 100644
--- a/pkg/trait/knative_test.go
+++ b/pkg/trait/knative_test.go
@@ -50,10 +50,12 @@ func TestKnativeTraitWithCompressedSources(t *testing.T) {
                                Profile: v1alpha1.TraitProfileKnative,
                                Sources: []v1alpha1.SourceSpec{
                                        {
-                                               Language:    
v1alpha1.LanguageJavaScript,
-                                               Name:        "routes.js",
-                                               Content:     content,
-                                               Compression: true,
+                                               DataSpec: v1alpha1.DataSpec{
+                                                       Name:        
"routes.js",
+                                                       Content:     content,
+                                                       Compression: true,
+                                               },
+                                               Language: 
v1alpha1.LanguageJavaScript,
                                        },
                                },
                        },
diff --git a/pkg/trait/springboot.go b/pkg/trait/springboot.go
index f8d87b9..fb280ba 100644
--- a/pkg/trait/springboot.go
+++ b/pkg/trait/springboot.go
@@ -23,9 +23,6 @@ import (
 
        "github.com/apache/camel-k/pkg/util/envvar"
 
-       "github.com/operator-framework/operator-sdk/pkg/sdk"
-       "github.com/pkg/errors"
-
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
        "github.com/apache/camel-k/pkg/builder"
        "github.com/apache/camel-k/pkg/builder/springboot"
@@ -52,7 +49,7 @@ func (t *springBootTrait) Configure(e *Environment) (bool, 
error) {
        if 
e.IntegrationContextInPhase(v1alpha1.IntegrationContextPhaseBuilding) {
                return true, nil
        }
-       if e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) {
+       if e.InPhase(v1alpha1.IntegrationContextPhaseReady, 
v1alpha1.IntegrationPhaseDeploying) {
                return true, nil
        }
        if e.IntegrationInPhase("") {
@@ -68,46 +65,47 @@ func (t *springBootTrait) Apply(e *Environment) error {
        // Integration
        //
 
-       if e.Integration != nil && e.Integration.Status.Phase == "" {
+       if e.IntegrationInPhase("") {
                util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, 
"runtime:spring-boot")
 
                // sort the dependencies to get always the same list if they 
don't change
                sort.Strings(e.Integration.Spec.Dependencies)
        }
 
-       if e.Integration != nil && e.Integration.Status.Phase == 
v1alpha1.IntegrationPhaseDeploying {
+       if e.InPhase(v1alpha1.IntegrationContextPhaseReady, 
v1alpha1.IntegrationPhaseDeploying) {
+               // Remove classpath
+               envvar.Remove(&e.EnvVars, "JAVA_CLASSPATH")
+
                // Override env vars
                envvar.SetVal(&e.EnvVars, "JAVA_MAIN_CLASS", 
"org.springframework.boot.loader.PropertiesLauncher")
                envvar.SetVal(&e.EnvVars, "LOADER_PATH", 
"/deployments/dependencies/")
 
-               if e.Integration.Spec.Context != "" {
-                       name := e.Integration.Spec.Context
-                       ctx := 
v1alpha1.NewIntegrationContext(e.Integration.Namespace, name)
+               deps := make([]string, 0, 2+len(e.Context.Status.Artifacts))
+               deps = append(deps, "/etc/camel/resources")
+               deps = append(deps, "./resources")
 
-                       if err := sdk.Get(&ctx); err != nil {
-                               return errors.Wrapf(err, "unable to find 
integration context %s, %s", ctx.Name, err)
+               for _, artifact := range e.Context.Status.Artifacts {
+                       if strings.HasPrefix(artifact.ID, 
"org.apache.camel.k:camel-k-runtime-spring-boot:") {
+                               // do not include runner jar
+                               continue
                        }
-
-                       deps := make([]string, 0, len(ctx.Status.Artifacts))
-                       for _, artifact := range ctx.Status.Artifacts {
-                               if strings.HasPrefix(artifact.ID, 
"org.apache.camel.k:camel-k-runtime-spring-boot:") {
-                                       // do not include runner jar
-                                       continue
-                               }
-
-                               deps = append(deps, artifact.Target)
+                       if strings.HasPrefix(artifact.ID, 
"org.apache.logging.log4j:") {
+                               // do not include logging, deps are embedded in 
runner jar
+                               continue
                        }
 
-                       envvar.SetVal(&e.EnvVars, "LOADER_HOME", "/deployments")
-                       envvar.SetVal(&e.EnvVars, "LOADER_PATH", 
strings.Join(deps, ","))
+                       deps = append(deps, artifact.Target)
                }
+
+               envvar.SetVal(&e.EnvVars, "LOADER_HOME", "/deployments")
+               envvar.SetVal(&e.EnvVars, "LOADER_PATH", strings.Join(deps, 
","))
        }
 
        //
        // Integration Context
        //
 
-       if e.Context != nil && e.Context.Status.Phase == 
v1alpha1.IntegrationContextPhaseBuilding {
+       if 
e.IntegrationContextInPhase(v1alpha1.IntegrationContextPhaseBuilding) {
                // add custom initialization logic
                e.Steps = append(e.Steps, 
builder.NewStep("initialize/spring-boot", builder.InitPhase, 
springboot.Initialize))
                e.Steps = append(e.Steps, 
builder.NewStep("build/compute-boot-dependencies", builder.ProjectBuildPhase+1, 
springboot.ComputeDependencies))
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index 6c9b89a..e2490d2 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -176,9 +176,11 @@ func createTestEnv(cluster 
v1alpha1.IntegrationPlatformCluster, script string) *
                        Spec: v1alpha1.IntegrationSpec{
                                Sources: []v1alpha1.SourceSpec{
                                        {
-                                               Name:     "file.groovy",
+                                               DataSpec: v1alpha1.DataSpec{
+                                                       Name:    "file.groovy",
+                                                       Content: script,
+                                               },
                                                Language: 
v1alpha1.LanguageGroovy,
-                                               Content:  script,
                                        },
                                },
                        },
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 5803a97..67054fb 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -49,12 +49,20 @@ func ComputeForIntegration(integration 
*v1alpha1.Integration) (string, error) {
                }
        }
 
+       // Integration resources
+       for _, item := range integration.Spec.Resources {
+               if _, err := hash.Write([]byte(item.Content)); err != nil {
+                       return "", err
+               }
+       }
+
        // Integration dependencies
        for _, item := range integration.Spec.Dependencies {
                if _, err := hash.Write([]byte(item)); err != nil {
                        return "", err
                }
        }
+
        // Integration configuration
        for _, item := range integration.Spec.Configuration {
                if _, err := hash.Write([]byte(item.String())); err != nil {
diff --git a/pkg/util/envvar/envvar.go b/pkg/util/envvar/envvar.go
index 68f6ba7..d8739cf 100644
--- a/pkg/util/envvar/envvar.go
+++ b/pkg/util/envvar/envvar.go
@@ -30,6 +30,17 @@ func Get(vars []v1.EnvVar, name string) *v1.EnvVar {
        return nil
 }
 
+// Remove --
+func Remove(vars *[]v1.EnvVar, name string) {
+       v := *vars
+       for i := 0; i < len(v); i++ {
+               if v[i].Name == name {
+                       *vars = append(v[:i], v[i+1:]...)
+                       return
+               }
+       }
+}
+
 // SetVal --
 func SetVal(vars *[]v1.EnvVar, name string, value string) {
        envVar := Get(*vars, name)

Reply via email to