You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2018/12/20 11:30:37 UTC
[camel-k] 01/03: add resources to an integration #241
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 <lb...@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)