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)