This is an automated email from the ASF dual-hosted git repository. pcongiusti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/main by this push: new 64dc4fcce fix(trait): cron replace only related components 64dc4fcce is described below commit 64dc4fccef812bd20b70b6f5b24d33d2cad4960d Author: Pasquale Congiusti <pasquale.congiu...@gmail.com> AuthorDate: Thu Jun 19 18:26:40 2025 +0200 fix(trait): cron replace only related components Closes #6161 --- pkg/util/source/inspector_groovy.go | 52 ++++++++++++--------- pkg/util/source/inspector_groovy_test.go | 18 ++++++++ pkg/util/source/inspector_java_script.go | 24 +--------- pkg/util/source/inspector_java_script_test.go | 18 ++++++++ pkg/util/source/inspector_java_source.go | 21 +-------- pkg/util/source/inspector_java_source_test.go | 18 ++++++++ pkg/util/source/inspector_kotlin.go | 22 +-------- pkg/util/source/inspector_kotlin_test.go | 18 ++++++++ pkg/util/source/inspector_xml.go | 4 +- pkg/util/source/inspector_xml_test.go | 66 ++++++++++++++++++++++++++- pkg/util/source/inspector_yaml.go | 8 +++- pkg/util/source/inspector_yaml_test.go | 64 +++++++++++++++++++++----- 12 files changed, 230 insertions(+), 103 deletions(-) diff --git a/pkg/util/source/inspector_groovy.go b/pkg/util/source/inspector_groovy.go index 57ecba6c7..bd85c53a4 100644 --- a/pkg/util/source/inspector_groovy.go +++ b/pkg/util/source/inspector_groovy.go @@ -18,12 +18,20 @@ limitations under the License. package source import ( - "strings" + "fmt" + "regexp" v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/util" ) +var ( + replaceURISingleQuotedFrom = regexp.MustCompile(`from\s*\(\s*'(?:timer|cron|quartz)[^']*'\s*\)`) + replaceURISingleQuotedFromF = regexp.MustCompile(`fromF\s*\(\s*'(?:timer|cron|quartz)[^']*'\s*\)`) + replaceURIDoubleQuotedFrom = regexp.MustCompile(`from\s*\(\s*"(?:timer|cron|quartz)[^"]*"\s*\)`) + replaceURIDoubleQuotedFromF = regexp.MustCompile(`fromF\s*\(\s*"(?:timer|cron|quartz)[^"]*"\s*\)`) +) + // GroovyInspector inspects Groovy DSL spec. type GroovyInspector struct { baseInspector @@ -61,25 +69,25 @@ func (i GroovyInspector) Extract(source v1.SourceSpec, meta *Metadata) error { // ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. Returns true if it applies a replacement. func (i GroovyInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { - froms := util.FindAllDistinctStringSubmatch( - source.Content, - singleQuotedFrom, - doubleQuotedFrom, - singleQuotedFromF, - doubleQuotedFromF, - ) - newContent := source.Content - if froms == nil { - return false, nil - } - for _, from := range froms { - newContent = strings.ReplaceAll(newContent, from, newFromURI) - } - replaced := newContent != source.Content - - if replaced { - source.Content = newContent - } - - return replaced, nil + return replaceFromURI(source, newFromURI) +} + +func replaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { + originalContent := source.Content + + source.Content = replaceURISingleQuotedFrom.ReplaceAllString(source.Content, fmt.Sprintf("from('%s')", newFromURI)) + source.Content = replaceURISingleQuotedFromF.ReplaceAllString(source.Content, fmt.Sprintf("fromF('%s')", newFromURI)) + source.Content = replaceURIDoubleQuotedFrom.ReplaceAllString(source.Content, fmt.Sprintf(`from("%s")`, newFromURI)) + source.Content = replaceURIDoubleQuotedFromF.ReplaceAllString(source.Content, fmt.Sprintf(`fromF('%s')`, newFromURI)) + + return originalContent != source.Content, nil +} + +func replaceFromURIDoubleQuotesOnly(source *v1.SourceSpec, newFromURI string) (bool, error) { + originalContent := source.Content + + source.Content = replaceURIDoubleQuotedFrom.ReplaceAllString(source.Content, fmt.Sprintf(`from("%s")`, newFromURI)) + source.Content = replaceURIDoubleQuotedFromF.ReplaceAllString(source.Content, fmt.Sprintf(`fromF('%s')`, newFromURI)) + + return originalContent != source.Content, nil } diff --git a/pkg/util/source/inspector_groovy_test.go b/pkg/util/source/inspector_groovy_test.go index c89e1c5dc..f595936fc 100644 --- a/pkg/util/source/inspector_groovy_test.go +++ b/pkg/util/source/inspector_groovy_test.go @@ -203,3 +203,21 @@ func TestGroovyReplaceURI(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"log:info\")", sourceSpec.Content) } + +func TestGroovyMultiReplaceURI(t *testing.T) { + inspector := newTestGroovyInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.groovy", + Content: "from('quartz:trigger?cron=0 0/1 * * * ?').to('direct:d1');from('direct:d1').to('log:info')", + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + assert.Equal(t, "from('direct:newURI?hello=world').to('direct:d1');from('direct:d1').to('log:info')", sourceSpec.Content) +} diff --git a/pkg/util/source/inspector_java_script.go b/pkg/util/source/inspector_java_script.go index c54b18881..cef88834f 100644 --- a/pkg/util/source/inspector_java_script.go +++ b/pkg/util/source/inspector_java_script.go @@ -18,8 +18,6 @@ limitations under the License. package source import ( - "strings" - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/util" ) @@ -61,25 +59,5 @@ func (i JavaScriptInspector) Extract(source v1.SourceSpec, meta *Metadata) error // ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. Returns true if it applies a replacement. func (i JavaScriptInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { - froms := util.FindAllDistinctStringSubmatch( - source.Content, - singleQuotedFrom, - doubleQuotedFrom, - singleQuotedFromF, - doubleQuotedFromF, - ) - newContent := source.Content - if froms == nil { - return false, nil - } - for _, from := range froms { - newContent = strings.ReplaceAll(newContent, from, newFromURI) - } - replaced := newContent != source.Content - - if replaced { - source.Content = newContent - } - - return replaced, nil + return replaceFromURI(source, newFromURI) } diff --git a/pkg/util/source/inspector_java_script_test.go b/pkg/util/source/inspector_java_script_test.go index 8c860acfb..c777d0279 100644 --- a/pkg/util/source/inspector_java_script_test.go +++ b/pkg/util/source/inspector_java_script_test.go @@ -185,3 +185,21 @@ func TestJavascriptReplaceURI(t *testing.T) { assert.True(t, replaced) assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"log:info\")", sourceSpec.Content) } + +func TestJavascriptMultiReplaceURI(t *testing.T) { + inspector := newTestJavaScriptInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.js", + Content: "from('quartz:trigger?cron=0 0/1 * * * ?').to('direct:d1');from('direct:d1').to('log:info')", + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + assert.Equal(t, "from('direct:newURI?hello=world').to('direct:d1');from('direct:d1').to('log:info')", sourceSpec.Content) +} diff --git a/pkg/util/source/inspector_java_source.go b/pkg/util/source/inspector_java_source.go index 6486bdcef..74b4bd9f7 100644 --- a/pkg/util/source/inspector_java_source.go +++ b/pkg/util/source/inspector_java_source.go @@ -18,8 +18,6 @@ limitations under the License. package source import ( - "strings" - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/util" ) @@ -55,22 +53,5 @@ func (i JavaSourceInspector) Extract(source v1.SourceSpec, meta *Metadata) error // ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. Returns true if it applies a replacement. func (i JavaSourceInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { - froms := util.FindAllDistinctStringSubmatch( - source.Content, - doubleQuotedFrom, - doubleQuotedFromF, - ) - newContent := source.Content - if froms == nil { - return false, nil - } - for _, from := range froms { - newContent = strings.ReplaceAll(newContent, from, newFromURI) - } - replaced := newContent != source.Content - if replaced { - source.Content = newContent - } - - return replaced, nil + return replaceFromURIDoubleQuotesOnly(source, newFromURI) } diff --git a/pkg/util/source/inspector_java_source_test.go b/pkg/util/source/inspector_java_source_test.go index 0ecc4b5c3..24f7241b4 100644 --- a/pkg/util/source/inspector_java_source_test.go +++ b/pkg/util/source/inspector_java_source_test.go @@ -172,6 +172,24 @@ func TestJavaReplaceURI(t *testing.T) { assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"log:info\")", sourceSpec.Content) } +func TestJavaReplaceMultiURI(t *testing.T) { + inspector := newTestJavaSourceInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.java", + Content: "from(\"quartz:trigger?cron=0 0/1 * * * ?\").to(\"direct:d1\");from(\"direct:d1\").to(\"log:info\");", + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"direct:d1\");from(\"direct:d1\").to(\"log:info\");", sourceSpec.Content) +} + func TestJavaRestOpenapiFirst(t *testing.T) { inspector := newTestJavaSourceInspector(t) diff --git a/pkg/util/source/inspector_kotlin.go b/pkg/util/source/inspector_kotlin.go index bdf57afe7..14eff39ad 100644 --- a/pkg/util/source/inspector_kotlin.go +++ b/pkg/util/source/inspector_kotlin.go @@ -18,8 +18,6 @@ limitations under the License. package source import ( - "strings" - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/util" ) @@ -55,23 +53,5 @@ func (i KotlinInspector) Extract(source v1.SourceSpec, meta *Metadata) error { // ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. Returns true if it applies a replacement. func (i KotlinInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { - froms := util.FindAllDistinctStringSubmatch( - source.Content, - doubleQuotedFrom, - doubleQuotedFromF, - ) - newContent := source.Content - if froms == nil { - return false, nil - } - for _, from := range froms { - newContent = strings.ReplaceAll(newContent, from, newFromURI) - } - replaced := newContent != source.Content - - if replaced { - source.Content = newContent - } - - return replaced, nil + return replaceFromURIDoubleQuotesOnly(source, newFromURI) } diff --git a/pkg/util/source/inspector_kotlin_test.go b/pkg/util/source/inspector_kotlin_test.go index 3e5b9c3b0..a332ad950 100644 --- a/pkg/util/source/inspector_kotlin_test.go +++ b/pkg/util/source/inspector_kotlin_test.go @@ -171,3 +171,21 @@ func TestKotlinReplaceURI(t *testing.T) { assert.True(t, replaced) assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"log:info\")", sourceSpec.Content) } + +func TestKotlinReplaceMultiURI(t *testing.T) { + inspector := newTestKotlinInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.java", + Content: "from(\"quartz:trigger?cron=0 0/1 * * * ?\").to(\"direct:d1\");from(\"direct:d1\").to(\"log:info\");", + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"direct:d1\");from(\"direct:d1\").to(\"log:info\");", sourceSpec.Content) +} diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go index 521f96242..91ebf98f3 100644 --- a/pkg/util/source/inspector_xml.go +++ b/pkg/util/source/inspector_xml.go @@ -140,7 +140,9 @@ func (i XMLInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) ( return false, nil } for _, from := range metadata.FromURIs { - newContent = strings.ReplaceAll(newContent, from, newFromURI) + if strings.HasPrefix(from, "timer") || strings.HasPrefix(from, "cron") || strings.HasPrefix(from, "quartz") { + newContent = strings.ReplaceAll(newContent, from, newFromURI) + } } replaced := newContent != source.Content diff --git a/pkg/util/source/inspector_xml_test.go b/pkg/util/source/inspector_xml_test.go index 1b770141a..182228851 100644 --- a/pkg/util/source/inspector_xml_test.go +++ b/pkg/util/source/inspector_xml_test.go @@ -112,6 +112,50 @@ const xmlJSONEip = ` </camelContext> ` +const xmlReplaceURI = ` +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="timer:start"/> + <to uri="log:info"/> + </route> +</camelContext> +` + +const expectedXmlReplaceURI = ` +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:newURI?hello=world"/> + <to uri="log:info"/> + </route> +</camelContext> +` + +const xmlReplaceMultiURI = ` +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="cron:tab"/> + <to uri="direct:d1"/> + </route> + <route> + <from uri="direct:d1"/> + <to uri="log:info"/> + </route> +</camelContext> +` + +const expectedXmlReplaceMultiURI = ` +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:newURI?hello=world"/> + <to uri="direct:d1"/> + </route> + <route> + <from uri="direct:d1"/> + <to uri="log:info"/> + </route> +</camelContext> +` + const xmlJSONJacksonEip = ` <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> @@ -194,7 +238,25 @@ func TestXMLReplaceURI(t *testing.T) { sourceSpec := &v1.SourceSpec{ DataSpec: v1.DataSpec{ Name: "test.xml", - Content: xmlJSONEip, + Content: xmlReplaceURI, + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + assert.Equal(t, expectedXmlReplaceURI, sourceSpec.Content) +} + +func TestXMLReplaceMultiURI(t *testing.T) { + inspector := newTestXMLInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.xml", + Content: xmlReplaceMultiURI, }, } replaced, err := inspector.ReplaceFromURI( @@ -203,7 +265,7 @@ func TestXMLReplaceURI(t *testing.T) { ) assert.Nil(t, err) assert.True(t, replaced) - assert.Contains(t, sourceSpec.Content, "<from uri=\"direct:newURI?hello=world\"/>") + assert.Equal(t, expectedXmlReplaceMultiURI, sourceSpec.Content) } func TestXMLRestOpenapiFirst(t *testing.T) { diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go index 840aaaf10..9d83879b4 100644 --- a/pkg/util/source/inspector_yaml.go +++ b/pkg/util/source/inspector_yaml.go @@ -238,7 +238,8 @@ func (i YAMLInspector) parseStepsParam(steps []interface{}, meta *Metadata) erro return nil } -// ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. Returns true if it applies a replacement. +// ReplaceFromURI parses the source content and replace the `from` URI configuration with the a new URI. +// Returns true if it applies a replacement. func (i YAMLInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) (bool, error) { definitions := make([]map[string]interface{}, 0) @@ -264,7 +265,10 @@ func (i YAMLInspector) ReplaceFromURI(source *v1.SourceSpec, newFromURI string) } } delete(from, "parameters") - from["uri"] = newFromURI + oldURI, ok := from["uri"].(string) + if ok && (strings.HasPrefix(oldURI, "timer") || strings.HasPrefix(oldURI, "cron") || strings.HasPrefix(oldURI, "quartz")) { + from["uri"] = newFromURI + } } newContentRaw, err := yaml2.Marshal(definitions) diff --git a/pkg/util/source/inspector_yaml_test.go b/pkg/util/source/inspector_yaml_test.go index a94c25491..af688756e 100644 --- a/pkg/util/source/inspector_yaml_test.go +++ b/pkg/util/source/inspector_yaml_test.go @@ -672,24 +672,45 @@ const yamlFromCronReplacement = ` - to: "{{url}}" ` -const expectedYamlFromCronReplacement = `from: +const yamlFromMultiCronReplacement = ` +- from: + uri: "cron:tab" + parameters: + schedule: "* * * * ?" + steps: + - to: "direct:hello" +- from: + uri: "direct:hello" + steps: + - setBody: + constant: "Hello Yaml !!!" + - transform: + simple: "${body.toUpperCase()}" + - to: "{{url}}" +` + +const expectedYamlFromMultiCronReplacement = `- from: + steps: + - to: direct:hello + uri: direct:newURI?hello=world +- from: steps: - setBody: constant: Hello Yaml !!! - transform: simple: ${body.toUpperCase()} - to: '{{url}}' - uri: direct:newURI?hello=world + uri: direct:hello ` -const expectedYamlRouteCronReplacement = `from: - steps: - - setBody: - constant: Hello Yaml !!! - - transform: - simple: ${body.toUpperCase()} - - to: '{{url}}' - uri: direct:newURI?hello=world +const expectedYamlFromCronReplacement = `from: + steps: + - setBody: + constant: Hello Yaml !!! + - transform: + simple: ${body.toUpperCase()} + - to: '{{url}}' + uri: direct:newURI?hello=world ` func TestYAMLFromReplaceURI(t *testing.T) { @@ -717,7 +738,7 @@ func TestYAMLRouteReplaceURI(t *testing.T) { sourceSpec := &v1.SourceSpec{ DataSpec: v1.DataSpec{ Name: "test.yaml", - Content: yamlRouteCronReplacement, + Content: yamlFromCronReplacement, }, } replaced, err := inspector.ReplaceFromURI( @@ -727,7 +748,26 @@ func TestYAMLRouteReplaceURI(t *testing.T) { assert.Nil(t, err) assert.True(t, replaced) // Assert changed uri and removed parameters - assert.Contains(t, sourceSpec.Content, expectedYamlRouteCronReplacement) + assert.Contains(t, sourceSpec.Content, expectedYamlFromCronReplacement) +} + +func TestYAMLFromWithMultiRouteReplaceURI(t *testing.T) { + inspector := newTestYAMLInspector(t) + + sourceSpec := &v1.SourceSpec{ + DataSpec: v1.DataSpec{ + Name: "test.yaml", + Content: yamlFromMultiCronReplacement, + }, + } + replaced, err := inspector.ReplaceFromURI( + sourceSpec, + "direct:newURI?hello=world", + ) + assert.Nil(t, err) + assert.True(t, replaced) + // Assert changed cron uri only + assert.Equal(t, expectedYamlFromMultiCronReplacement, sourceSpec.Content) } func TestYAMLRESTContractFirst(t *testing.T) {