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 676f40f fix(kamelets): error handler uri autodiscovery 676f40f is described below commit 676f40f1378555357b4954e3539c0395e7ac9df5 Author: Pasquale Congiusti <pasquale.congiu...@gmail.com> AuthorDate: Wed Aug 25 17:42:39 2021 +0200 fix(kamelets): error handler uri autodiscovery * Discovery and setting depedencies when using directly a URI * Refactoring inspector.go and runtime catalog in order to reuse biz logic Closes #2492 --- pkg/trait/error_handler.go | 26 ++++++++- pkg/trait/error_handler_test.go | 93 +++++++++++++++++++++++++++++++++ pkg/util/camel/camel_runtime_catalog.go | 15 ++++++ pkg/util/source/inspector.go | 18 +------ 4 files changed, 135 insertions(+), 17 deletions(-) diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go index 547ac52..dfb4799 100644 --- a/pkg/trait/error_handler.go +++ b/pkg/trait/error_handler.go @@ -18,6 +18,9 @@ limitations under the License. package trait import ( + "fmt" + "strings" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "gopkg.in/yaml.v2" @@ -34,7 +37,8 @@ type errorHandlerTrait struct { func newErrorHandlerTrait() Trait { return &errorHandlerTrait{ - BaseTrait: NewBaseTrait("error-handler", 500), + // NOTE: Must run before dependency trait + BaseTrait: NewBaseTrait("error-handler", 470), } } @@ -61,11 +65,31 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) { func (t *errorHandlerTrait) Apply(e *Environment) error { if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + // If the user configure directly the URI, we need to autodiscover the underlying component + // and add the related dependency + defaultErrorHandlerURI := e.Integration.Spec.GetConfigurationProperty( + fmt.Sprintf("%s.deadLetterUri", v1alpha1.ErrorHandlerAppPropertiesPrefix)) + if defaultErrorHandlerURI != "" && !strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") { + t.addErrorHandlerDependencies(e, defaultErrorHandlerURI) + } + return t.addErrorHandlerAsSource(e) } return nil } +func (t *errorHandlerTrait) addErrorHandlerDependencies(e *Environment, uri string) { + candidateComp, scheme := e.CamelCatalog.DecodeComponent(uri) + if candidateComp != nil { + e.Integration.Spec.AddDependency(candidateComp.GetDependencyID()) + if scheme != nil { + for _, dep := range candidateComp.GetProducerDependencyIDs(scheme.ID) { + e.Integration.Spec.AddDependency(dep) + } + } + } +} + func (t *errorHandlerTrait) addErrorHandlerAsSource(e *Environment) error { flowErrorHandler := map[string]interface{}{ "error-handler": map[string]string{ diff --git a/pkg/trait/error_handler_test.go b/pkg/trait/error_handler_test.go new file mode 100644 index 0000000..c77d1ba --- /dev/null +++ b/pkg/trait/error_handler_test.go @@ -0,0 +1,93 @@ +/* +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" + "testing" + + "github.com/stretchr/testify/assert" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/apache/camel-k/pkg/util/camel" +) + +func TestErrorHandlerConfigureFromIntegrationProperty(t *testing.T) { + e := &Environment{ + Catalog: NewEnvironmentTestCatalog(), + Integration: &v1.Integration{}, + } + e.Integration.Spec.AddConfiguration("property", fmt.Sprintf("%v = %s", v1alpha1.ErrorHandlerRefName, "defaultErrorHandler")) + + trait := newErrorHandlerTrait() + enabled, err := trait.Configure(e) + assert.Nil(t, err) + assert.False(t, enabled) + + e.Integration.Status.Phase = v1.IntegrationPhaseNone + enabled, err = trait.Configure(e) + assert.Nil(t, err) + assert.False(t, enabled) + + e.Integration.Status.Phase = v1.IntegrationPhaseInitialization + enabled, err = trait.Configure(e) + assert.Nil(t, err) + assert.True(t, enabled) +} + +func TestErrorHandlerApplySource(t *testing.T) { + e := &Environment{ + Catalog: NewEnvironmentTestCatalog(), + Integration: &v1.Integration{}, + } + e.Integration.Spec.AddConfiguration("property", fmt.Sprintf("%v = %s", v1alpha1.ErrorHandlerRefName, "defaultErrorHandler")) + e.Integration.Status.Phase = v1.IntegrationPhaseInitialization + + trait := newErrorHandlerTrait() + enabled, err := trait.Configure(e) + assert.Nil(t, err) + assert.True(t, enabled) + err = trait.Apply(e) + assert.Nil(t, err) + assert.Equal(t, `- error-handler: + ref: defaultErrorHandler +`, e.Integration.Status.GeneratedSources[0].Content) +} + +func TestErrorHandlerApplyDependency(t *testing.T) { + c, err := camel.DefaultCatalog() + assert.Nil(t, err) + e := &Environment{ + Catalog: NewEnvironmentTestCatalog(), + CamelCatalog: c, + Integration: &v1.Integration{}, + } + e.Integration.Spec.AddConfiguration("property", "camel.beans.defaultErrorHandler = #class:org.apache.camel.builder.DeadLetterChannelBuilder") + e.Integration.Spec.AddConfiguration("property", "camel.beans.defaultErrorHandler.deadLetterUri = log:info") + e.Integration.Spec.AddConfiguration("property", fmt.Sprintf("%v = %s", v1alpha1.ErrorHandlerRefName, "defaultErrorHandler")) + e.Integration.Status.Phase = v1.IntegrationPhaseInitialization + + trait := newErrorHandlerTrait() + enabled, err := trait.Configure(e) + assert.Nil(t, err) + assert.True(t, enabled) + err = trait.Apply(e) + assert.Nil(t, err) + assert.Equal(t, "camel:log", e.Integration.Spec.Dependencies[0]) +} diff --git a/pkg/util/camel/camel_runtime_catalog.go b/pkg/util/camel/camel_runtime_catalog.go index dc71a40..e726685 100644 --- a/pkg/util/camel/camel_runtime_catalog.go +++ b/pkg/util/camel/camel_runtime_catalog.go @@ -146,3 +146,18 @@ func (c *RuntimeCatalog) VisitSchemes(visitor func(string, v1.CamelScheme) bool) } } } + +// DecodeComponent parses an 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 { + return nil, nil + } + uriStart := uriSplit[0] + scheme, ok := c.GetScheme(uriStart) + var schemeRef *v1.CamelScheme + if ok { + schemeRef = &scheme + } + return c.GetArtifactByScheme(uriStart), schemeRef +} diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go index c2f80fd..9ed9b87 100644 --- a/pkg/util/source/inspector.go +++ b/pkg/util/source/inspector.go @@ -239,7 +239,7 @@ func (i *baseInspector) discoverCapabilities(source v1.SourceSpec, meta *Metadat // discoverDependencies returns a list of dependencies required by the given source code func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadata) { for _, uri := range meta.FromURIs { - candidateComp, scheme := i.decodeComponent(uri) + candidateComp, scheme := i.catalog.DecodeComponent(uri) if candidateComp != nil { i.addDependency(candidateComp.GetDependencyID(), meta) if scheme != nil { @@ -251,7 +251,7 @@ func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadat } for _, uri := range meta.ToURIs { - candidateComp, scheme := i.decodeComponent(uri) + candidateComp, scheme := i.catalog.DecodeComponent(uri) if candidateComp != nil { i.addDependency(candidateComp.GetDependencyID(), meta) if scheme != nil { @@ -303,20 +303,6 @@ func (i *baseInspector) addDependency(dependency string, meta *Metadata) { meta.Dependencies.Add(dependency) } -func (i *baseInspector) decodeComponent(uri string) (*v1.CamelArtifact, *v1.CamelScheme) { - uriSplit := strings.SplitN(uri, ":", 2) - if len(uriSplit) < 2 { - return nil, nil - } - uriStart := uriSplit[0] - scheme, ok := i.catalog.GetScheme(uriStart) - var schemeRef *v1.CamelScheme - if ok { - schemeRef = &scheme - } - return i.catalog.GetArtifactByScheme(uriStart), schemeRef -} - // hasOnlyPassiveEndpoints returns true if the source has no endpoint that needs to remain always active func (i *baseInspector) hasOnlyPassiveEndpoints(fromURIs []string) bool { passivePlusHTTP := make(map[string]bool)