Skip to content

Commit

Permalink
fix(apache#3896): Fix dependency inspector supporting property placeh…
Browse files Browse the repository at this point in the history
…olders

Do not raise errors during dependency inspection when using property placeholders in URIs. Fixes http-sink Kamelet which uses {{url}} as endpoint URI
  • Loading branch information
christophd authored and squakez committed Jan 10, 2023
1 parent d1af7f9 commit fe2571e
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 1 deletion.
18 changes: 17 additions & 1 deletion pkg/util/camel/camel_runtime_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (c *RuntimeCatalog) VisitSchemes(visitor func(string, v1.CamelScheme) bool)
}
}

// DecodeComponent parses an URI and return a camel artifact and a scheme.
// DecodeComponent parses the given URI and return a camel artifact and a scheme.
func (c *RuntimeCatalog) DecodeComponent(uri string) (*v1.CamelArtifact, *v1.CamelScheme) {
uriSplit := strings.SplitN(uri, ":", 2)
if len(uriSplit) < 2 {
Expand All @@ -192,3 +192,19 @@ func (c *RuntimeCatalog) DecodeComponent(uri string) (*v1.CamelArtifact, *v1.Cam
}
return c.GetArtifactByScheme(uriStart), schemeRef
}

// IsResolvable checks given URI for proper Camel format (e.g. resolvable scheme).
func (c *RuntimeCatalog) IsResolvable(uri string) bool {
uriSplit := strings.SplitN(uri, ":", 2)

if len(uriSplit) == 0 {
return false
}

if scheme := uriSplit[0]; strings.HasPrefix(scheme, "{{") && strings.HasSuffix(scheme, "}}") {
// scheme is a property placeholder (e.g. {{url}}) which is not resolvable
return false
}

return true
}
7 changes: 7 additions & 0 deletions pkg/util/source/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,14 @@ func (i *baseInspector) discoverKamelets(meta *Metadata) {
}

func (i *baseInspector) addDependencies(uri string, meta *Metadata, consumer bool) error {
if !i.catalog.IsResolvable(uri) {
// ignore dependencies for given URI as it is not resolvable in this state
// (e.g. using a property placeholder such as {{url} or {{scheme}}:{{resource}})
return nil
}

candidateComp, scheme := i.catalog.DecodeComponent(uri)

if candidateComp == nil || scheme == nil {
return fmt.Errorf("component not found for uri %q in camel catalog runtime version %s",
uri, i.catalog.GetRuntimeVersion())
Expand Down
98 changes: 98 additions & 0 deletions pkg/util/source/inspector_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package source

import (
"fmt"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -545,3 +546,100 @@ func TestYAMLExplicitParameters(t *testing.T) {
})
}
}

const yamlFromDSLWithPropertyPlaceholder = `
- route:
id: route1
from:
uri: "timer:tick"
parameters:
period: "5000"
steps:
- set-body:
constant: "Hello Yaml !!!"
- transform:
simple: "${body.toUpperCase()}"
- to: "{{url}}"
`

const yamlFromDSLWithPropertyPlaceholderScheme = `
- route:
id: route2
from:
uri: "timer:tick"
parameters:
period: "5000"
steps:
- set-body:
constant: "Hello Yaml !!!"
- transform:
simple: "${body.toUpperCase()}"
- to: "{{scheme}}:{{resource}}"
`

func TestYAMLRouteWithPropertyPlaceholder(t *testing.T) {
tc := []struct {
source string
fromURIs []string
toURIs []string
}{
{
source: yamlFromDSLWithPropertyPlaceholder,
fromURIs: []string{"timer:tick?period=5000"},
toURIs: []string{"{{url}}"},
},
{
source: yamlFromDSLWithPropertyPlaceholderScheme,
fromURIs: []string{"timer:tick?period=5000"},
toURIs: []string{"{{scheme}}:{{resource}}"},
},
}

inspector := newTestYAMLInspector(t)
for i, test := range tc {
t.Run(fmt.Sprintf("TestYAMLRouteWithPropertyPlaceholder-%d", i), func(t *testing.T) {
assertExtractYAML(t, inspector, test.source, func(meta *Metadata) {
assert.Len(t, meta.FromURIs, len(test.fromURIs))
for _, k := range test.fromURIs {
assert.Contains(t, meta.FromURIs, k)
}
assert.Len(t, meta.ToURIs, len(test.toURIs))
for _, k := range test.toURIs {
assert.Contains(t, meta.ToURIs, k)
}
assert.Equal(t, meta.Dependencies.Size(), 2)
assert.True(t, meta.Dependencies.Has("camel:core"))
assert.True(t, meta.Dependencies.Has("camel:timer"))
})
})
}
}

const yamlFromDSLWithUnknownFromScheme = `
- route:
id: route1
from:
uri: "unknown:foo"
steps:
- to: "log:info"
`

const yamlFromDSLWithUnknownToScheme = `
- route:
id: route2
from:
uri: "timer:tick"
steps:
- to: "unknown:foo"
`

func TestYAMLRouteWithUnknownScheme(t *testing.T) {
inspector := newTestYAMLInspector(t)
for i, source := range []string{yamlFromDSLWithUnknownFromScheme, yamlFromDSLWithUnknownToScheme} {
t.Run(fmt.Sprintf("TestYAMLRouteWithUnknownScheme-%d", i), func(t *testing.T) {
assertExtractYAMLError(t, inspector, source, func(err error) {
assert.True(t, strings.HasPrefix(err.Error(), fmt.Sprintf("component not found for uri %q", "unknown:foo")))
})
})
}
}
17 changes: 17 additions & 0 deletions pkg/util/source/test_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,20 @@ func assertExtractYAML(t *testing.T, inspector YAMLInspector, source string, ass

assertFn(&meta)
}

func assertExtractYAMLError(t *testing.T, inspector YAMLInspector, source string, assertFn func(err error)) {
t.Helper()

srcSpec := v1.SourceSpec{
DataSpec: v1.DataSpec{
Name: "route.yaml",
Content: source,
},
Language: v1.LanguageYaml,
}
meta := NewMetadata()
err := inspector.Extract(srcSpec, &meta)
require.Error(t, err)

assertFn(err)
}

0 comments on commit fe2571e

Please sign in to comment.