You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2021/05/11 06:36:52 UTC

[camel-k] 19/33: refactor(trait): error handler to bean ref

This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch release-1.4.x
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit d1c4284bacb4496ef4957f1e26f12fe07058452b
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Apr 23 17:09:59 2021 +0200

    refactor(trait): error handler to bean ref
---
 pkg/apis/camel/v1/common_types.go                  | 12 ----
 pkg/apis/camel/v1/integration_types.go             |  9 ++-
 pkg/apis/camel/v1/integration_types_support.go     | 27 +++++++++
 pkg/apis/camel/v1alpha1/error_handler_types.go     | 39 ++++++++++++-
 pkg/controller/kameletbinding/error_handler.go     | 24 +++-----
 .../kameletbinding/error_handler_test.go           | 13 ++++-
 pkg/trait/error_handler.go                         | 68 +++-------------------
 pkg/trait/kamelets.go                              |  9 +--
 8 files changed, 102 insertions(+), 99 deletions(-)

diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go
index 71774fc..e5b327b 100644
--- a/pkg/apis/camel/v1/common_types.go
+++ b/pkg/apis/camel/v1/common_types.go
@@ -162,18 +162,6 @@ type Flow struct {
 	RawMessage `json:",inline"`
 }
 
-// ErrorHandlerSpec respresents an integration error handler to be used as default at runtime
-type ErrorHandlerSpec struct {
-	Type       string                  `json:"type,omitempty"`
-	URI        string                  `json:"uri,omitempty"`
-	Parameters *ErrorHandlerParameters `json:"parameters,omitempty"`
-}
-
-// ErrorHandlerParameters is an unstructured object representing the configuration parameters available for an error handler
-type ErrorHandlerParameters struct {
-	RawMessage `json:",inline"`
-}
-
 // RuntimeProvider --
 type RuntimeProvider string
 
diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go
index 500291c..6ba7e10 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -27,11 +27,10 @@ import (
 
 // IntegrationSpec defines the desired state of Integration
 type IntegrationSpec struct {
-	Replicas     *int32           `json:"replicas,omitempty"`
-	Sources      []SourceSpec     `json:"sources,omitempty"`
-	ErrorHandler ErrorHandlerSpec `json:"errorHandler,omitempty"`
-	Flows        []Flow           `json:"flows,omitempty"`
-	Resources    []ResourceSpec   `json:"resources,omitempty"`
+	Replicas  *int32         `json:"replicas,omitempty"`
+	Sources   []SourceSpec   `json:"sources,omitempty"`
+	Flows     []Flow         `json:"flows,omitempty"`
+	Resources []ResourceSpec `json:"resources,omitempty"`
 	// Deprecated: use the IntegrationKit field
 	Kit                string                  `json:"kit,omitempty"`
 	IntegrationKit     *corev1.ObjectReference `json:"integrationKit,omitempty"`
diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go
index 53705c9..295c75a 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -131,6 +131,33 @@ func (in *IntegrationSpec) AddDependency(dependency string) {
 	in.Dependencies = append(in.Dependencies, newDep)
 }
 
+// HasDefaultErrorHandler checks the configuration properties to see if a default error handler is declared
+func (in *IntegrationSpec) HasDefaultErrorHandler() bool {
+	return in.GetDefaultErrorHandler() != ""
+}
+
+// GetDefaultErrorHandler returns the default error handler, if it is declared
+func (in *IntegrationSpec) GetDefaultErrorHandler() string {
+	return in.getConfigurationProperty("camel.beans.defaultErrorHandler")
+}
+
+// GetDefaultErrorHandlerURI returns the default error handler uri, if it is declared
+func (in *IntegrationSpec) GetDefaultErrorHandlerURI() string {
+	return in.getConfigurationProperty("camel.beans.defaultErrorHandler.uri")
+}
+
+func (in *IntegrationSpec) getConfigurationProperty(property string) string {
+	for _, confSpec := range in.Configuration {
+		if confSpec.Type == "property" && strings.HasPrefix(confSpec.Value, property) {
+			splitConf := strings.Split(confSpec.Value, "=")
+			if len(splitConf) > 0 {
+				return splitConf[1]
+			}
+		}
+	}
+	return ""
+}
+
 // AddOrReplaceGeneratedResources --
 func (in *IntegrationStatus) AddOrReplaceGeneratedResources(resources ...ResourceSpec) {
 	newResources := make([]ResourceSpec, 0)
diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index 1969e2b..d40bf6f 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -18,9 +18,13 @@ limitations under the License.
 package v1alpha1
 
 import (
+	"encoding/json"
+
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
+const errorHandlerAppPropertiesPrefix = "camel.beans.defaultErrorHandler"
+
 // ErrorHandlerSpec represents an unstructured object for an error handler
 type ErrorHandlerSpec struct {
 	v1.RawMessage `json:",omitempty"`
@@ -43,6 +47,7 @@ type ErrorHandler interface {
 	Endpoint() *Endpoint
 	Ref() *string
 	Bean() *string
+	Configuration() (map[string]interface{}, error)
 }
 
 type abstractErrorHandler struct {
@@ -68,11 +73,16 @@ func (e abstractErrorHandler) Ref() *string {
 	return nil
 }
 
-// Ref --
+// Bean --
 func (e abstractErrorHandler) Bean() *string {
 	return nil
 }
 
+// Configuration --
+func (e abstractErrorHandler) Configuration() (map[string]interface{}, error) {
+	return nil, nil
+}
+
 // ErrorHandlerNone --
 type ErrorHandlerNone struct {
 	*abstractErrorHandler
@@ -83,6 +93,13 @@ func (e ErrorHandlerNone) Type() ErrorHandlerType {
 	return ErrorHandlerTypeNone
 }
 
+// Configuration --
+func (e ErrorHandlerNone) Configuration() (map[string]interface{}, error) {
+	return map[string]interface{}{
+		errorHandlerAppPropertiesPrefix: "#class:org.apache.camel.builder.NoErrorHandlerBuilder",
+	}, nil
+}
+
 // ErrorHandlerLog represent a default (log) error handler type
 type ErrorHandlerLog struct {
 	*abstractErrorHandler
@@ -99,6 +116,26 @@ func (e ErrorHandlerLog) Params() *ErrorHandlerParameters {
 	return e.Parameters
 }
 
+// Configuration --
+func (e ErrorHandlerLog) Configuration() (map[string]interface{}, error) {
+	properties := map[string]interface{}{
+		errorHandlerAppPropertiesPrefix: "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder",
+	}
+
+	if e.Params() != nil {
+		var parameters map[string]interface{}
+		err := json.Unmarshal(e.Params().RawMessage, &parameters)
+		if err != nil {
+			return nil, err
+		}
+		for key, value := range parameters {
+			properties[errorHandlerAppPropertiesPrefix+"."+key] = value
+		}
+	}
+
+	return properties, nil
+}
+
 // ErrorHandlerDeadLetterChannel represents a dead letter channel error handler type
 type ErrorHandlerDeadLetterChannel struct {
 	*ErrorHandlerLog
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index 15e72bb..0cf95b6 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -19,6 +19,7 @@ package kameletbinding
 
 import (
 	"encoding/json"
+	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -33,21 +34,17 @@ func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandlerSpec, bindingContext bi
 		if err != nil {
 			return nil, errors.Wrap(err, "could not parse error handler")
 		}
+		// We need to get the translated URI from any referenced resource (ie, kamelets)
 		errorHandlerURI := ""
 		if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeDeadLetterChannel {
 			errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, *errorHandlerSpec.Endpoint())
 			if err != nil {
 				return nil, errors.Wrap(err, "could not determine error handler URI")
 			}
-
 			errorHandlerURI = errorHandler.URI
-		} else if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeRef {
-			errorHandlerURI = *errorHandlerSpec.Ref()
-		} else if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeBean {
-			errorHandlerURI = *errorHandlerSpec.Bean()
 		}
 
-		err = setIntegrationErrorHandler(itSpec, errorHandlerURI, errorHandlerSpec)
+		err = setErrorHandlerConfiguration(itSpec, errorHandlerURI, errorHandlerSpec)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not set integration error handler")
 		}
@@ -95,16 +92,13 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.ErrorHandler, error)
 	return nil, errors.New("You must provide any supported error handler (none, log, dead-letter-channel)")
 }
 
-func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandlerURI string, errorHandlerSpec v1alpha1.ErrorHandler) error {
-	it.ErrorHandler = v1.ErrorHandlerSpec{
-		Type: string(errorHandlerSpec.Type()),
-	}
-	if errorHandlerSpec.Params() != nil {
-		it.ErrorHandler.Parameters = &v1.ErrorHandlerParameters{errorHandlerSpec.Params().RawMessage}
+func setErrorHandlerConfiguration(it *v1.IntegrationSpec, errorHandlerURI string, errorHandler v1alpha1.ErrorHandler) error {
+	properties, err := errorHandler.Configuration()
+	if err != nil {
+		return err
 	}
-	if errorHandlerURI != "" {
-		it.ErrorHandler.URI = errorHandlerURI
+	for key, value := range properties {
+		it.AddConfiguration("property", fmt.Sprintf("%s=%v", key, value))
 	}
-
 	return nil
 }
diff --git a/pkg/controller/kameletbinding/error_handler_test.go b/pkg/controller/kameletbinding/error_handler_test.go
index 40864b9..e05caf4 100644
--- a/pkg/controller/kameletbinding/error_handler_test.go
+++ b/pkg/controller/kameletbinding/error_handler_test.go
@@ -30,6 +30,9 @@ func TestParseErrorHandlerNoneDoesSucceed(t *testing.T) {
 	)
 	assert.Nil(t, err)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeNone, noErrorHandler.Type())
+	parameters, err := noErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:org.apache.camel.builder.NoErrorHandlerBuilder", parameters["camel.beans.defaultErrorHandler"])
 }
 
 func TestParseErrorHandlerLogDoesSucceed(t *testing.T) {
@@ -38,15 +41,23 @@ func TestParseErrorHandlerLogDoesSucceed(t *testing.T) {
 	)
 	assert.Nil(t, err)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeLog, logErrorHandler.Type())
+	parameters, err := logErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder", parameters["camel.beans.defaultErrorHandler"])
 }
 
 func TestParseErrorHandlerLogWithParametersDoesSucceed(t *testing.T) {
 	logErrorHandler, err := parseErrorHandler(
-		[]byte(`{"log": {"parameters": [{"param1": "value1"}, {"param2": "value2"}]}}`),
+		[]byte(`{"log": {"parameters": {"param1": "value1", "param2": "value2"}}}`),
 	)
 	assert.Nil(t, err)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeLog, logErrorHandler.Type())
 	assert.NotNil(t, logErrorHandler.Params())
+	parameters, err := logErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder", parameters["camel.beans.defaultErrorHandler"])
+	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.param1"])
+	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.param2"])
 }
 
 func TestParseErrorHandlerDLCDoesSucceed(t *testing.T) {
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index c2aee73..b7a8c0d 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -18,7 +18,6 @@ limitations under the License.
 package trait
 
 import (
-	"encoding/json"
 	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
@@ -51,41 +50,33 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	return e.Integration.Spec.ErrorHandler.Type != "", nil
+	return e.Integration.Spec.HasDefaultErrorHandler(), nil
 }
 
 func (t *errorHandlerTrait) Apply(e *Environment) error {
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		if e.Integration.Spec.ErrorHandler.Type != "" {
-			// Possible error handler
-			err := addErrorHandlerAsSource(e)
-			if err != nil {
-				return err
-			}
+		err := addErrorHandlerAsSource(e)
+		if err != nil {
+			return err
 		}
 	}
 	return nil
 }
 
 func addErrorHandlerAsSource(e *Environment) error {
-	errorHandlerStatement, err := parseErrorHandler(e)
-	if err != nil {
-		return err
-	}
-
 	// TODO change to yaml flow when we fix https://issues.apache.org/jira/browse/CAMEL-16486
 	errorHandlerSource := v1.SourceSpec{
 		DataSpec: v1.DataSpec{
 			Name: "ErrorHandlerSource.java",
-			Content: fmt.Sprintf(`
+			Content: `
 			import org.apache.camel.builder.RouteBuilder;
 			public class ErrorHandlerSource extends RouteBuilder {
 			@Override
 			public void configure() throws Exception {
-			  %s
+				errorHandler("defaultErrorHandler");
 			  }
 			}
-			`, errorHandlerStatement),
+			`,
 		},
 		Language: v1.LanguageJavaSource,
 		Type:     v1.SourceTypeErrorHandler,
@@ -104,48 +95,3 @@ func addErrorHandlerBeanConfiguration(e *Environment, fqn string) error {
 	})
 	return nil
 }
-
-func parseErrorHandler(e *Environment) (string, error) {
-	errorHandlerSpec := e.Integration.Spec.ErrorHandler
-	switch errorHandlerSpec.Type {
-	case "none":
-		return `errorHandler(noErrorHandler());`, nil
-	case "log":
-		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Parameters)
-		if err != nil {
-			return "", err
-		}
-
-		return fmt.Sprintf(`errorHandler(defaultErrorHandler()%v);`, errorHandlerConfiguration), nil
-	case "dead-letter-channel":
-		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Parameters)
-		if err != nil {
-			return "", err
-		}
-
-		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v")%v);`, errorHandlerSpec.URI, errorHandlerConfiguration), nil
-	case "ref":
-		// TODO using URI temporarily, fix it properly
-		return fmt.Sprintf(`errorHandler("%v");`, errorHandlerSpec.URI), nil
-	case "bean":
-		// TODO using URI temporarily, fix it properly
-		addErrorHandlerBeanConfiguration(e, errorHandlerSpec.URI)
-		return fmt.Sprintf(`errorHandler("%v");`, "defaultErrorHandler"), nil
-	}
-
-	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errorHandlerSpec.Type)
-}
-
-func parseErrorHandlerConfiguration(conf *v1.ErrorHandlerParameters) (string, error) {
-	javaPropertiesBuilder := ""
-	var properties map[string]interface{}
-	err := json.Unmarshal(conf.RawMessage, &properties)
-	if err != nil {
-		return "", err
-	}
-	for method, value := range properties {
-		javaPropertiesBuilder = javaPropertiesBuilder + fmt.Sprintf(".%s(%v)\n", method, value)
-	}
-
-	return javaPropertiesBuilder, nil
-}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 57ec4b5..83a35a9 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -106,10 +106,11 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 				return true
 			})
 		}
-		// Check if a Kamelet is configured as default error handler
-		if e.Integration.Spec.ErrorHandler.URI != "" {
-			if strings.HasPrefix(e.Integration.Spec.ErrorHandler.URI, "kamelet:") {
-				kamelets = append(kamelets, extractKamelet(e.Integration.Spec.ErrorHandler.URI))
+		// Check if a Kamelet is configured as default error handler URI
+		defaultErrorHandlerURI := e.Integration.Spec.GetDefaultErrorHandlerURI()
+		if defaultErrorHandlerURI != "" {
+			if strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") {
+				kamelets = append(kamelets, extractKamelet(defaultErrorHandlerURI))
 			}
 		}