You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2021/04/29 13:12:14 UTC

[camel-k] branch main updated (fc0cc52 -> cc4e016)

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

nferraro pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git.


    from fc0cc52  Updated CHANGELOG.md
     new f7ad34d  feat(kamelets): error handling kamelets binding support
     new 1cbec51  doc(example): kameletbinding error handler
     new a488a3a  fix(kamelets): optional error handler
     new 1849ca5  feat(kamelets): error handling kamelets binding support
     new 619806d  feat(crd): kameletbinding error handler
     new 924378e  doc(example): error handling kamelet binding
     new 9287343  feat(trait): error handler trait
     new 34c82df  refactor(trait): integration error handler spec
     new 3b8ae4a  refactor(trait): error handler kamelet
     new 096e5de  doc(example): error handler DLC
     new 5eaff76  refactor(crd): updated crd after error-handler
     new 0aae942  doc(trait): error-handler generated doc
     new 647b82f  feat(trait): error handler advanced configuration
     new 68aaeb4  fix(trait): default error handler configuration setting
     new 92d1c5d  refactor(trait): error handler spec definition
     new d922c4a  chore(controller): error handler unit test
     new bb48d9a  feat(trait): error handler Ref
     new 7728261  feat(trait): error handler bean
     new df34cad  refactor(trait): error handler to bean ref
     new 5eb36ef  refactor(trait): error handler using bean ref
     new 71e0624  refactor(controller): app properties binding
     new d1a72fd  refactor(trait): error handler language to yaml
     new 2f621da  refactor(controller): error handler useless uri
     new 987fc9d  refactor(controller): error handler bean properties
     new 88d3706  chore(crd): error handler generated crds
     new 8b1974c  chore(doc): error handler generated
     new 8f91086  doc(kamelets): kamelet bindings error handler
     new 82df277  chore(trait): polishing PR
     new 855f4a7  feat(e2e): error handler integration test
     new cc4e016  doc(trait): regen

The 30 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../bases/camel.apache.org_kameletbindings.yaml    |   5 +
 .../1.4.0/camel.apache.org_kameletbindings.yaml    |  20 ++
 .../camel.apache.org_kameletbindings.yaml          |   5 +
 deploy/traits.yaml                                 |  16 ++
 docs/modules/ROOT/nav.adoc                         |   1 +
 .../kamelets/kameletbindings-error-handler.adoc    | 156 ++++++++++++++
 .../modules/ROOT/pages/kamelets/kamelets-user.adoc |   4 +
 docs/modules/ROOT/pages/kamelets/kamelets.adoc     |   1 +
 .../pages/{builder.adoc => error-handler.adoc}     |  17 +-
 .../js_test.go => traits/error_handler_test.go}    |  28 ++-
 .../traits/files/ErroredRoute.java}                |   9 +-
 .../error-handler/error-handler.kamelet.yaml       |  29 ++-
 .../incremental-id-source.kamelet.yaml             |  31 ++-
 .../kamelet-binding-error-handler.yaml             |  44 ++--
 .../log-sink.kamelet.yaml}                         |  24 +--
 examples/kamelets/error-handler/readme.md          |  71 +++++++
 helm/camel-k/crds/crd-kamelet-binding.yaml         |   5 +
 pkg/apis/camel/v1/common_types.go                  |   5 +-
 pkg/apis/camel/v1/integration_types_support.go     |  13 ++
 pkg/apis/camel/v1alpha1/error_handler_types.go     | 229 +++++++++++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |   9 +-
 pkg/controller/kameletbinding/common.go            |  17 +-
 pkg/controller/kameletbinding/error_handler.go     | 110 ++++++++++
 .../kameletbinding/error_handler_test.go           | 134 ++++++++++++
 pkg/resources/resources.go                         |   2 +-
 pkg/trait/error_handler.go                         |  91 ++++++++
 pkg/trait/kamelets.go                              |  28 ++-
 pkg/trait/trait_register.go                        |   1 +
 pkg/trait/trait_test.go                            |   2 +-
 29 files changed, 1003 insertions(+), 104 deletions(-)
 create mode 100644 docs/modules/ROOT/pages/kamelets/kameletbindings-error-handler.adoc
 copy docs/modules/traits/pages/{builder.adoc => error-handler.adoc} (58%)
 copy e2e/common/{languages/js_test.go => traits/error_handler_test.go} (54%)
 copy e2e/{builder/files/Java.java => common/traits/files/ErroredRoute.java} (83%)
 copy e2e/yaks/common/kamelet-steps/prefix-action.kamelet.yaml => examples/kamelets/error-handler/error-handler.kamelet.yaml (72%)
 copy e2e/yaks/common/kamelet-binding-http/timer-source.kamelet.yaml => examples/kamelets/error-handler/incremental-id-source.kamelet.yaml (69%)
 copy e2e/yaks/common/kamelet-steps/steps-binding.yaml => examples/kamelets/error-handler/kamelet-binding-error-handler.yaml (63%)
 copy examples/kamelets/{timer-source-log-sink/log-sink.binding.yaml => error-handler/log-sink.kamelet.yaml} (79%)
 create mode 100644 examples/kamelets/error-handler/readme.md
 create mode 100644 pkg/apis/camel/v1alpha1/error_handler_types.go
 create mode 100644 pkg/controller/kameletbinding/error_handler.go
 create mode 100644 pkg/controller/kameletbinding/error_handler_test.go
 create mode 100644 pkg/trait/error_handler.go

[camel-k] 30/30: doc(trait): regen

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit cc4e01653f1ada233a0cd04d89485e33e2e2c0fa
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 28 14:42:54 2021 +0200

    doc(trait): regen
---
 deploy/traits.yaml                           | 4 ++--
 docs/modules/traits/pages/error-handler.adoc | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index b2c3af3..6f90900 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -284,9 +284,9 @@ traits:
     type: bool
     description: Can be used to enable or disable a trait. All traits share this common
       property.
-  - name: error-handler-ref
+  - name: ref
     type: string
-    description: The error handler ref name found in application properties
+    description: The error handler ref name provided or found in application properties
 - name: gc
   platform: false
   profiles:
diff --git a/docs/modules/traits/pages/error-handler.adoc b/docs/modules/traits/pages/error-handler.adoc
index 978e76f..7ddfd17 100755
--- a/docs/modules/traits/pages/error-handler.adoc
+++ b/docs/modules/traits/pages/error-handler.adoc
@@ -27,9 +27,9 @@ The following configuration options are available:
 | bool
 | Can be used to enable or disable a trait. All traits share this common property.
 
-| error-handler.error-handler-ref
+| error-handler.ref
 | string
-| The error handler ref name found in application properties
+| The error handler ref name provided or found in application properties
 
 |===
 

[camel-k] 26/30: chore(doc): error handler generated

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 8b1974ca12b48b9d48f4f08d3aacfb3e3ecb4d6a
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 11:31:56 2021 +0200

    chore(doc): error handler generated
---
 deploy/traits.yaml                           | 9 ++++++++-
 docs/modules/traits/pages/error-handler.adoc | 6 +++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index 0c567dd..22cc617 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -279,7 +279,14 @@ traits:
   - OpenShift
   description: The error-handler is a platform trait used to inject Error Handler
     source into the integration runtime.
-  properties: []
+  properties:
+  - name: enabled
+    type: bool
+    description: Can be used to enable or disable a trait. All traits share this common
+      property.
+  - name: ',omitempty'
+    type: string
+    description: The error handler ref name found in application properties
 - name: gc
   platform: false
   profiles:
diff --git a/docs/modules/traits/pages/error-handler.adoc b/docs/modules/traits/pages/error-handler.adoc
index 0c38c7d..149eaee 100755
--- a/docs/modules/traits/pages/error-handler.adoc
+++ b/docs/modules/traits/pages/error-handler.adoc
@@ -15,7 +15,7 @@ WARNING: The error-handler trait is a *platform trait*: disabling it may comprom
 Trait properties can be specified when running any integration with the CLI:
 [source,console]
 ----
-$ kamel run --trait error-handler.[key]=[value] integration.groovy
+$ kamel run --trait error-handler.[key]=[value] --trait error-handler.[key2]=[value2] integration.groovy
 ----
 The following configuration options are available:
 
@@ -27,6 +27,10 @@ The following configuration options are available:
 | bool
 | Can be used to enable or disable a trait. All traits share this common property.
 
+| error-handler.,omitempty
+| string
+| The error handler ref name found in application properties
+
 |===
 
 // End of autogenerated code - DO NOT EDIT! (configuration)

[camel-k] 08/30: refactor(trait): integration error handler spec

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 34c82df0eea0b75e4dece804604732eec13d50ef
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 10:04:02 2021 +0200

    refactor(trait): integration error handler spec
---
 pkg/apis/camel/v1/common_types.go       | 12 +++++++
 pkg/apis/camel/v1/integration_types.go  |  9 ++---
 pkg/controller/kameletbinding/common.go | 14 ++++----
 pkg/trait/error_handler.go              | 59 +++++----------------------------
 pkg/trait/kamelets.go                   | 19 +++++------
 5 files changed, 39 insertions(+), 74 deletions(-)

diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go
index e5b327b..e1b27e1 100644
--- a/pkg/apis/camel/v1/common_types.go
+++ b/pkg/apis/camel/v1/common_types.go
@@ -162,6 +162,18 @@ 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"`
+	Configuration *ErrorHandlerConfiguration `json:"configuration,omitempty"`
+}
+
+// ErrorHandlerConfiguration --
+type ErrorHandlerConfiguration 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 6ba7e10..500291c 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -27,10 +27,11 @@ import (
 
 // IntegrationSpec defines the desired state of Integration
 type IntegrationSpec struct {
-	Replicas  *int32         `json:"replicas,omitempty"`
-	Sources   []SourceSpec   `json:"sources,omitempty"`
-	Flows     []Flow         `json:"flows,omitempty"`
-	Resources []ResourceSpec `json:"resources,omitempty"`
+	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"`
 	// Deprecated: use the IntegrationKit field
 	Kit                string                  `json:"kit,omitempty"`
 	IntegrationKit     *corev1.ObjectReference `json:"integrationKit,omitempty"`
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index a63780f..13e13fe 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -86,9 +86,9 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 			return nil, errors.Wrap(err, "could not determine error handler URI")
 		}
 
-		err = setErrorHandlerKamelet(errorHandler, kameletbinding.Spec.ErrorHandler)
+		err = setIntegrationErrorHandler(&it.Spec, errorHandler, kameletbinding.Spec.ErrorHandler)
 		if err != nil {
-			return nil, errors.Wrap(err, "could not set error handler")
+			return nil, errors.Wrap(err, "could not set integration error handler")
 		}
 	}
 
@@ -159,14 +159,12 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	return &it, nil
 }
 
-func setErrorHandlerKamelet(errorHandler *bindings.Binding, errorHandlerSpec v1alpha1.ErrorHandler) error {
-	if errorHandler.ApplicationProperties == nil {
-		errorHandler.ApplicationProperties = make(map[string]string)
+func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandler *bindings.Binding, errorHandlerSpec v1alpha1.ErrorHandler) error {
+	it.ErrorHandler = v1.ErrorHandlerSpec{
+		URI:  errorHandler.URI,
+		Type: string(errorHandlerSpec.Type),
 	}
 
-	errorHandler.ApplicationProperties["camel.k.default-error-handler.uri"] = errorHandler.URI
-	errorHandler.ApplicationProperties["camel.k.default-error-handler.type"] = string(errorHandlerSpec.Type)
-
 	return nil
 }
 
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index 7101d9e..228ed12 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -19,10 +19,8 @@ package trait
 
 import (
 	"fmt"
-	"strings"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
 // The error handler is a platform trait used to inject Error Handler source into the integration runtime.
@@ -30,12 +28,7 @@ import (
 // +camel-k:trait=error-handler
 type errorHandlerTrait struct {
 	BaseTrait `property:",squash"`
-	// Automatically inject all referenced Kamelets and their default configuration (enabled by default)
-	Auto *bool `property:"auto"`
-
-	// TODO move into a struct
-	ErrorHandlerURI  string
-	ErrorHandlerType string
+	Auto      *bool `property:"auto"`
 }
 
 func newErrorHandlerTrait() Trait {
@@ -58,50 +51,14 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	if t.Auto == nil || *t.Auto {
-		if t.ErrorHandlerType == "" {
-			t.ErrorHandlerType = maybeErrorHandler(e.Integration.Configurations())
-			if t.ErrorHandlerType != "" && v1alpha1.ErrorHandlerType(t.ErrorHandlerType) == v1alpha1.ErrorHandlerTypeDeadLetterChannel {
-				t.ErrorHandlerURI = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
-			}
-		}
-	}
-
-	return t.ErrorHandlerType != "", nil
-}
-
-func maybeErrorHandler(properties []v1.ConfigurationSpec) string {
-	for _, property := range properties {
-		if strings.HasPrefix(property.Value, "camel.k.default-error-handler.type=") {
-			split := strings.Split(property.Value, "=")
-			if len(split) > 0 {
-				return split[1]
-			}
-		}
-	}
-
-	return ""
-}
-
-func maybeKameletAsDefaultErrorHandler(properties []v1.ConfigurationSpec) string {
-	for _, property := range properties {
-		if strings.HasPrefix(property.Value, "camel.k.default-error-handler.uri=") {
-			split := strings.Split(property.Value, "=")
-			if len(split) > 0 {
-				return split[1]
-			}
-		}
-	}
-
-	return ""
+	return e.Integration.Spec.ErrorHandler.Type != "", nil
 }
 
 func (t *errorHandlerTrait) Apply(e *Environment) error {
-
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		if t.ErrorHandlerType != "" {
+		if e.Integration.Spec.ErrorHandler.Type != "" {
 			// Possible error handler
-			err := addErrorHandlerAsSource(e, t.ErrorHandlerURI, t.ErrorHandlerType)
+			err := addErrorHandlerAsSource(e)
 			if err != nil {
 				return err
 			}
@@ -110,8 +67,8 @@ func (t *errorHandlerTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func addErrorHandlerAsSource(e *Environment, errorHandlerURI string, errorHandlerType string) error {
-	errorHandlerStatement, err := parseErrorHandler(errorHandlerURI, errorHandlerType)
+func addErrorHandlerAsSource(e *Environment) error {
+	errorHandlerStatement, err := parseErrorHandler(e.Integration.Spec.ErrorHandler.URI, e.Integration.Spec.ErrorHandler.Type)
 	if err != nil {
 		return err
 	}
@@ -148,14 +105,14 @@ func addErrorHandlerAsSource(e *Environment, errorHandlerURI string, errorHandle
 	return nil
 }
 
-func parseErrorHandler(errHandlUri string, errHandlType string) (string, error) {
+func parseErrorHandler(errHandlURI string, errHandlType string) (string, error) {
 	switch errHandlType {
 	case "no":
 		return `errorHandler(noErrorHandler());`, nil
 	case "default":
 		return `errorHandler(defaultErrorHandler());`, nil
 	case "dead-letter-channel":
-		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v"));`, errHandlUri), nil
+		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v"));`, errHandlURI), nil
 	}
 
 	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errHandlType)
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index dd4c3bb..190c17e 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -47,10 +47,6 @@ type kameletsTrait struct {
 	Auto *bool `property:"auto"`
 	// Comma separated list of Kamelet names to load into the current integration
 	List string `property:"list"`
-
-	// TODO move into a struct
-	ErrorHandlerURI  string
-	ErrorHandlerType string
 }
 
 type configurationKey struct {
@@ -111,13 +107,10 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 			})
 			sort.Strings(kamelets)
 		}
-		if t.ErrorHandlerType == "" {
-			t.ErrorHandlerType = maybeErrorHandler(e.Integration.Configurations())
-			if t.ErrorHandlerType != "" && v1alpha1.ErrorHandlerType(t.ErrorHandlerType) == v1alpha1.ErrorHandlerTypeDeadLetterChannel {
-				t.ErrorHandlerURI = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
-				if strings.HasPrefix(t.ErrorHandlerURI, "kamelet:") {
-					kamelets = append(kamelets, extractKamelet(t.ErrorHandlerURI))
-				}
+		// 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))
 			}
 		}
 
@@ -132,8 +125,12 @@ func (t *kameletsTrait) declaredKamelets() bool {
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
+<<<<<<< HEAD
 
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseRunning) {
+=======
+	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+>>>>>>> refactor(trait): integration error handler spec
 		if err := t.addKamelets(e); err != nil {
 			return err
 		}

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

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit df34cad4b8cd4d5003fb4f512518010cd7eacd50
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))
 			}
 		}
 

[camel-k] 10/30: doc(example): error handler DLC

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 096e5de959593a4521300e0ffe669b6ec8fbd8a2
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 15:14:19 2021 +0200

    doc(example): error handler DLC
---
 .../error-handler/error-handler.kamelet.yaml       | 35 +++++++++++-----------
 .../kamelet-binding-error-handler.yaml             | 13 ++++----
 examples/kamelets/error-handler/readme.md          | 30 +++++++++++--------
 3 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/examples/kamelets/error-handler/error-handler.kamelet.yaml b/examples/kamelets/error-handler/error-handler.kamelet.yaml
index dbfc4bb..9ace959 100644
--- a/examples/kamelets/error-handler/error-handler.kamelet.yaml
+++ b/examples/kamelets/error-handler/error-handler.kamelet.yaml
@@ -20,21 +20,22 @@ kind: Kamelet
 metadata:
   name: error-handler
 spec:
-  sources:
-  - content: |
-      import org.apache.camel.builder.RouteBuilder;
-      public class ErrorHandlerSource extends RouteBuilder {
-        @Override
-        public void configure() throws Exception {
-            errorHandler(deadLetterChannel("log:error?showCaughtException=true&showException=true&showHeaders=true"));
-        }
-      }
-    name: ErrorHandlerSource.java
   definition:
-    title: "Error Handler Log DLC"
-    description: "Dead letter channel"
-# We can use the below once this is fixed https://issues.apache.org/jira/browse/CAMEL-16486
-#  flow:
-#    error-handler:
-#      dead-letter-channel:
-#        dead-letter-uri: log:error-sink?showCaughtException=true&showException=true&showHeaders=true
+    title: "Error Log Sink"
+    description: "Consume events from a channel"
+    required:
+      - message
+    properties:
+      message:
+        title: Message
+        description: The message to log
+        type: string
+        example: "error while checking the source"    
+  flow:
+    from:
+      uri: kamelet:source
+      steps:
+#      - to: my-dlc
+      - set-body:
+          constant: "{{message}}"
+      - to: "log:error-sink"  
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index 3602831..ae8eb78 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -31,9 +31,12 @@ spec:
       apiVersion: camel.apache.org/v1alpha1
       name: log-sink
   errorHandler:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: error-handler    
-#    uri: kamelet:error-handler
+    type: dead-letter-channel
+    endpoint:
+      ref:
+        kind: Kamelet
+        apiVersion: camel.apache.org/v1alpha1
+        name: error-handler
+      properties:
+        message: "ERROR!"   
     
diff --git a/examples/kamelets/error-handler/readme.md b/examples/kamelets/error-handler/readme.md
index 5ff4777..dc4d75b 100644
--- a/examples/kamelets/error-handler/readme.md
+++ b/examples/kamelets/error-handler/readme.md
@@ -1,5 +1,5 @@
 # Kamelets Binding Error Handler example
-This example shows how to create a simple _source_ `kamelet` bound to a log _sink_ in a `KameletBinding`. With the support of the `ErrorHandler` we will be able to redirect all errors to a `Dead Letter Channel` _error-handler_ `Kamelet`.
+This example shows how to create a simple _source_ `Kamelet` which sends periodically events (and certain failures). The events are consumed by a log _sink_ in a `KameletBinding`. With the support of the `ErrorHandler` we will be able to redirect all errors to a `Dead Letter Channel` _error-handler_ `Kamelet`.
 
 ## Incremental ID Source Kamelet
 First of all, you must install the _incremental-id-source_ Kamelet defined in `incremental-id-source.kamelet.yaml` file. This source will emit events every second with an autoincrement counter that will be forced to fail when the number 0 is caught. With this trick, we will simulate possible event faults.
@@ -26,8 +26,8 @@ NAME                    PHASE
 log-sink                Ready
 incremental-id-source   Ready
 ```
-## Error handler  Kamelet
-We finally install an error handler as a dead letter channel as specified in `error-handler.kamelet.yaml` file. You can specify any kind of error handler as expected by Apache Camel runtime.
+## Error handler Kamelet
+We finally install an error handler as specified in `error-handler.kamelet.yaml` file. This is a simple logger, but you can use any endpoint to collect and store the failing events.
 ```
 $ kubectl apply -f error-handler.kamelet.yaml
 ```
@@ -41,14 +41,18 @@ log-sink                Ready
 incremental-id-source   Ready
 ```
 ## Error Handler Kamelet Binding
-We can create a `KameletBinding` which is triggered by the _incremental-id-source_ `Kamelet` and log events to _log-sink_ `Kamelet`. As this will sporadically fail, we can configure an _errorHandler_ as defined in `kamelet-binding-error-handler.yaml` file:
+We can create a `KameletBinding` which is started by the _incremental-id-source_ `Kamelet` and log events to _log-sink_ `Kamelet`. As this will sporadically fail, we can configure an _errorHandler_ with the _error-handler_ `Kamelet` as **Dead Letter Channel**. We can declare it as in `kamelet-binding-error-handler.yaml` file:
 ```
 ...
   errorHandler:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: error-handler
+    type: dead-letter-channel
+    endpoint:
+      ref:
+        kind: Kamelet
+        apiVersion: camel.apache.org/v1alpha1
+        name: error-handler
+      properties:
+        message: "ERROR!"
 ```
 Execute the following command to start the `Integration`:
 ```
@@ -56,9 +60,9 @@ kubectl apply -f kamelet-binding-error-handler.yaml
 ```
 As soon as the `Integration` starts, it will log the events on the `ok` log channel and errors on the `error` log channel:
 ```
-[1] 2021-04-13 10:33:38,375 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #8]
-[1] 2021-04-13 10:33:39,376 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #9]
-[1] 2021-04-13 10:33:40,409 INFO  [error] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, Headers: {firedTime=Tue Apr 13 10:33:40 GMT 2021}, BodyType: String, Body: Producing message #10, CaughtExceptionType: org.apache.camel.CamelExecutionException, CaughtExceptionMessage: Exception occurred during execution on the exchange: Exchange[]]
-[1] 2021-04-13 10:33:41,375 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #11]
+[1] 2021-04-21 13:03:43,773 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #8]
+[1] 2021-04-21 13:03:44,774 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #9]
+[1] 2021-04-21 13:03:45,898 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR!]
+[1] 2021-04-21 13:03:46,775 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #11]
 ```
-This example is useful to guide you through the configuration of an error handler. In a production environment you will likely configure the error handler with a `Dead Letter Channel` pointing to a persistent queue.
\ No newline at end of file
+This example is useful to guide you through the configuration of an error handler. In a production environment you will likely configure the error handler `Kamelet` pointing to a persistent queue.
\ No newline at end of file

[camel-k] 29/30: feat(e2e): error handler integration test

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 855f4a74faca1b241a63cf4a5835e42d08efa453
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 28 14:39:06 2021 +0200

    feat(e2e): error handler integration test
---
 e2e/common/traits/error_handler_test.go   | 57 +++++++++++++++++++++++++++++++
 e2e/common/traits/files/ErroredRoute.java | 29 ++++++++++++++++
 pkg/trait/error_handler.go                |  8 +++--
 3 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/e2e/common/traits/error_handler_test.go b/e2e/common/traits/error_handler_test.go
new file mode 100644
index 0000000..506eba4
--- /dev/null
+++ b/e2e/common/traits/error_handler_test.go
@@ -0,0 +1,57 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 traits
+
+import (
+	"testing"
+
+	. "github.com/onsi/gomega"
+
+	v1 "k8s.io/api/core/v1"
+
+	. "github.com/apache/camel-k/e2e/support"
+	camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+)
+
+func TestErrorHandlerTrait(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		t.Run("Run errored integration with error handler", func(t *testing.T) {
+			name := "error-handler"
+			Expect(Kamel("run", "-n", ns, "files/ErroredRoute.java",
+				"--name", name,
+				"-t", "error-handler.enabled=true",
+				"-t", "error-handler.ref=defaultErrorHandler",
+				"-p", "camel.beans.defaultErrorHandler=#class:org.apache.camel.builder.DeadLetterChannelBuilder",
+				"-p", "camel.beans.defaultErrorHandler.deadLetterUri=log:my-special-error-handler-in-place?level=ERROR&showCaughtException=false&showBody=false&showBodyType=false&showExchangePattern=false",
+			).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, name), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+			Eventually(IntegrationCondition(ns, name, camelv1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(v1.ConditionTrue))
+			Eventually(IntegrationLogs(ns, name), TestTimeoutShort).ShouldNot(ContainSubstring("InvalidPayloadException"))
+			Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("my-special-error-handler-in-place"))
+		})
+
+		// Clean up
+		Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+	})
+}
diff --git a/e2e/common/traits/files/ErroredRoute.java b/e2e/common/traits/files/ErroredRoute.java
new file mode 100644
index 0000000..702e163
--- /dev/null
+++ b/e2e/common/traits/files/ErroredRoute.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class ErroredRoute extends RouteBuilder {
+  @Override
+  public void configure() throws Exception {
+	  from("timer:tick")
+    .setBody().simple("Hello")
+    // We want to force a failure
+	  .setBody().simple("${mandatoryBodyAs(Boolean)}")
+    .to("log:info");
+  }
+}
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index a72a94a..aa59b4e 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -28,8 +28,8 @@ import (
 // +camel-k:trait=error-handler
 type errorHandlerTrait struct {
 	BaseTrait `property:",squash"`
-	// The error handler ref name found in application properties
-	ErrorHandlerRef string `property:"error-handler-ref" json:"error-handler-ref,omitempty"`
+	// The error handler ref name provided or found in application properties
+	ErrorHandlerRef string `property:"ref" json:"ref,omitempty"`
 }
 
 func newErrorHandlerTrait() Trait {
@@ -52,7 +52,9 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	t.ErrorHandlerRef = e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName)
+	if t.ErrorHandlerRef == "" {
+		t.ErrorHandlerRef = e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName)
+	}
 
 	return t.ErrorHandlerRef != "", nil
 }

[camel-k] 17/30: feat(trait): error handler Ref

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit bb48d9ae9e482117d474027320dc1a222a0b1618
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Apr 23 10:04:58 2021 +0200

    feat(trait): error handler Ref
---
 pkg/apis/camel/v1alpha1/error_handler_types.go | 42 ++++++++++++++++++++++++++
 pkg/controller/kameletbinding/error_handler.go |  6 ++++
 pkg/trait/error_handler.go                     |  3 ++
 3 files changed, 51 insertions(+)

diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index df46324..949fbd6 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -36,6 +36,7 @@ type AbstractErrorHandler interface {
 	Type() ErrorHandlerType
 	Params() *ErrorHandlerProperties
 	Endpoint() *Endpoint
+	Ref() *string
 }
 
 // ErrorHandlerNone --
@@ -62,6 +63,11 @@ func (e ErrorHandlerNone) Endpoint() *Endpoint {
 	return nil
 }
 
+// Ref --
+func (e ErrorHandlerNone) Ref() *string {
+	return nil
+}
+
 // ErrorHandlerLog represent a default (log) error handler type
 type ErrorHandlerLog struct {
 	Parameters *ErrorHandlerProperties `json:"parameters,omitempty"`
@@ -82,6 +88,11 @@ func (e ErrorHandlerLog) Endpoint() *Endpoint {
 	return nil
 }
 
+// Ref --
+func (e ErrorHandlerLog) Ref() *string {
+	return nil
+}
+
 // ErrorHandlerDeadLetterChannel represents a dead letter channel error handler type
 type ErrorHandlerDeadLetterChannel struct {
 	*ErrorHandlerLog
@@ -103,6 +114,35 @@ func (e ErrorHandlerDeadLetterChannel) Endpoint() *Endpoint {
 	return e.DLCEndpoint
 }
 
+// Ref --
+func (e ErrorHandlerDeadLetterChannel) Ref() *string {
+	return nil
+}
+
+// ErrorHandlerRef represents a reference to an error handler builder available in the registry
+type ErrorHandlerRef string
+
+// Type --
+func (e ErrorHandlerRef) Type() ErrorHandlerType {
+	return ErrorHandlerTypeRef
+}
+
+// Params --
+func (e ErrorHandlerRef) Params() *ErrorHandlerProperties {
+	return nil
+}
+
+// Endpoint --
+func (e ErrorHandlerRef) Endpoint() *Endpoint {
+	return nil
+}
+
+// Ref --
+func (e ErrorHandlerRef) Ref() *string {
+	s := string(e)
+	return &s
+}
+
 // ErrorHandlerType --
 type ErrorHandlerType string
 
@@ -113,4 +153,6 @@ const (
 	ErrorHandlerTypeLog ErrorHandlerType = "log"
 	// ErrorHandlerTypeDeadLetterChannel --
 	ErrorHandlerTypeDeadLetterChannel ErrorHandlerType = "dead-letter-channel"
+	// ErrorHandlerTypeRef --
+	ErrorHandlerTypeRef ErrorHandlerType = "ref"
 )
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index 90ba3cc..c9858f9 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -43,6 +43,10 @@ func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandler, bindingContext bindin
 			errorHandlerURI = errorHandler.URI
 		}
 
+		if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeRef {
+			errorHandlerURI = *errorHandlerSpec.Ref()
+		}
+
 		err = setIntegrationErrorHandler(itSpec, errorHandlerURI, errorHandlerSpec)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not set integration error handler")
@@ -72,6 +76,8 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler,
 			dst = new(v1alpha1.ErrorHandlerLog)
 		case v1alpha1.ErrorHandlerTypeDeadLetterChannel:
 			dst = new(v1alpha1.ErrorHandlerDeadLetterChannel)
+		case v1alpha1.ErrorHandlerTypeRef:
+			dst = new(v1alpha1.ErrorHandlerRef)
 		default:
 			return nil, errors.Errorf("Unknown error type %s, supported error types are: none, log, dead-letter-channel", errHandlType)
 		}
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index e82dcf9..7945372 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -123,6 +123,9 @@ func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
 		}
 
 		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
 	}
 
 	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errorHandlerSpec.Type)

[camel-k] 01/30: feat(kamelets): error handling kamelets binding support

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit f7ad34d9d6b8ad5f41f0be56f43171db8c9a8537
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Mar 16 16:17:56 2021 +0100

    feat(kamelets): error handling kamelets binding support
    
    * Added the capability to include an `errorHandler` support that will be converted as an `error-handler` in the generated integration.
    * Fixed the inspector_yaml.go to parse the integration `error-handler` and load declared Kamelet source
---
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go |  9 ++++--
 pkg/controller/kameletbinding/common.go          | 36 +++++++++++++++++++++---
 pkg/trait/kamelets.go                            |  1 +
 pkg/util/source/inspector_yaml.go                |  4 +++
 pkg/util/source/types.go                         |  2 ++
 5 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 8fea2ac..b91ed55 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -32,6 +32,8 @@ type KameletBindingSpec struct {
 	Source Endpoint `json:"source,omitempty"`
 	// Sink is the destination of the integration defined by this binding
 	Sink Endpoint `json:"sink,omitempty"`
+	// ErrorHandler is an optional handler called upon an error occuring in the integration
+	ErrorHandler Endpoint `json:"errorHandler,omitempty"`
 	// Steps contains an optional list of intermediate steps that are executed between the Source and the Sink
 	Steps []Endpoint `json:"steps,omitempty"`
 }
@@ -51,9 +53,10 @@ type Endpoint struct {
 type EndpointType string
 
 const (
-	EndpointTypeSource EndpointType = "source"
-	EndpointTypeAction EndpointType = "action"
-	EndpointTypeSink   EndpointType = "sink"
+	EndpointTypeSource       EndpointType = "source"
+	EndpointTypeAction       EndpointType = "action"
+	EndpointTypeSink         EndpointType = "sink"
+	EndpointTypeErrorHandler EndpointType = "errorHandler"
 )
 
 // EndpointProperties is a key/value struct represented as JSON raw to allow numeric/boolean values
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 411bde8..354dfa2 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -79,6 +79,10 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
+	onError, err := bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
+	if err != nil {
+		return nil, errors.Wrap(err, "could not determine error handler URI")
+	}
 
 	steps := make([]*bindings.Binding, 0, len(kameletbinding.Spec.Steps))
 	for idx, step := range kameletbinding.Spec.Steps {
@@ -93,10 +97,13 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		steps = append(steps, stepBinding)
 	}
 
-	allBindings := make([]*bindings.Binding, 0, len(steps)+2)
+	allBindings := make([]*bindings.Binding, 0, len(steps)+3)
 	allBindings = append(allBindings, from)
 	allBindings = append(allBindings, steps...)
 	allBindings = append(allBindings, to)
+	if onError != nil {
+		allBindings = append(allBindings, onError)
+	}
 
 	propList := make([]string, 0)
 	for _, b := range allBindings {
@@ -129,17 +136,38 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		"to": to.URI,
 	})
 
-	flow := map[string]interface{}{
+	// Append Error Handler flow, if it exists
+	if onError != nil {
+		flowErrorHandler := map[string]interface{}{
+			"error-handler": map[string]interface{}{
+				"dead-letter-channel": map[string]interface{}{
+					"dead-letter-uri":                  onError.URI,
+					"dead-letter-handle-new-exception": true,
+					"async-delayed-redelivery":         false,
+					"use-original-message":             true,
+				},
+			},
+		}
+		encodedErrorHandler, err := json.Marshal(flowErrorHandler)
+
+		if err != nil {
+			return nil, err
+		}
+		it.Spec.Flows = append(it.Spec.Flows, v1.Flow{RawMessage: encodedErrorHandler})
+	}
+
+	// Append From flow: it must exist
+	flowFrom := map[string]interface{}{
 		"from": map[string]interface{}{
 			"uri":   from.URI,
 			"steps": dslSteps,
 		},
 	}
-	encodedFlow, err := json.Marshal(flow)
+	encodedFrom, err := json.Marshal(flowFrom)
 	if err != nil {
 		return nil, err
 	}
-	it.Spec.Flows = append(it.Spec.Flows, v1.Flow{RawMessage: encodedFlow})
+	it.Spec.Flows = append(it.Spec.Flows, v1.Flow{RawMessage: encodedFrom})
 
 	return &it, nil
 }
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index df437d9..9d55b19 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -103,6 +103,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.FromURIs))
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ToURIs))
+				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ErrorHandlerURIs))
 				return true
 			})
 			sort.Strings(kamelets)
diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go
index 1f96ae8..4c47dc2 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -78,6 +78,10 @@ func (i YAMLInspector) parseStep(key string, content interface{}, meta *Metadata
 				}
 			}
 		}
+	case "error-handler":
+		deadLetterChannel := content.(map[interface{}]interface{})
+		deadLetterURI := deadLetterChannel["dead-letter-channel"].(map[interface{}]interface{})
+		meta.ErrorHandlerURIs = append(meta.ErrorHandlerURIs, deadLetterURI["dead-letter-uri"].(string))
 	}
 
 	var maybeURI string
diff --git a/pkg/util/source/types.go b/pkg/util/source/types.go
index f6f15e0..46074f8 100644
--- a/pkg/util/source/types.go
+++ b/pkg/util/source/types.go
@@ -25,6 +25,8 @@ type Metadata struct {
 	FromURIs []string
 	// All end URIs of defined routes
 	ToURIs []string
+	// All error handlers URIs of defined routes
+	ErrorHandlerURIs []string
 	// All inferred dependencies required to run the integration
 	Dependencies *strset.Set
 	// ExposesHTTPServices indicates if a route defined by the source is exposed

[camel-k] 20/30: refactor(trait): error handler using bean ref

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 5eb36ef24edd436f9ce96b005ede00f8795d7b53
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Mon Apr 26 18:22:18 2021 +0200

    refactor(trait): error handler using bean ref
---
 pkg/apis/camel/v1/integration_types_support.go     |  18 +---
 pkg/apis/camel/v1alpha1/error_handler_types.go     | 119 ++++++++++++---------
 pkg/controller/kameletbinding/common.go            |   1 +
 pkg/controller/kameletbinding/error_handler.go     |   7 +-
 .../kameletbinding/error_handler_test.go           |  52 +++++++--
 pkg/trait/error_handler.go                         |  19 ++--
 pkg/trait/kamelets.go                              |  11 +-
 7 files changed, 122 insertions(+), 105 deletions(-)

diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go
index 295c75a..6efdc24 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -131,22 +131,8 @@ 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 {
+// GetConfigurationProperty returns a configuration property
+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, "=")
diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index d40bf6f..4f3f4e7 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -19,11 +19,19 @@ package v1alpha1
 
 import (
 	"encoding/json"
+	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-const errorHandlerAppPropertiesPrefix = "camel.beans.defaultErrorHandler"
+// ErrorHandlerRefName --
+const ErrorHandlerRefName = "camel.k.errorHandler.ref"
+
+// ErrorHandlerRefDefaultName --
+const ErrorHandlerRefDefaultName = "defaultErrorHandler"
+
+// ErrorHandlerAppPropertiesPrefix --
+const ErrorHandlerAppPropertiesPrefix = "camel.beans.defaultErrorHandler"
 
 // ErrorHandlerSpec represents an unstructured object for an error handler
 type ErrorHandlerSpec struct {
@@ -32,60 +40,42 @@ type ErrorHandlerSpec struct {
 
 // ErrorHandlerParameters represent an unstructured object for error handler parameters
 type ErrorHandlerParameters struct {
-	v1.RawMessage `json:",inline"`
+	v1.RawMessage `json:",omitempty"`
 }
 
 // BeanProperties represent an unstructured object properties to be set on a bean
 type BeanProperties struct {
-	v1.RawMessage `json:",inline"`
+	v1.RawMessage `json:",omitempty"`
 }
 
 // ErrorHandler is a generic interface that represent any type of error handler specification
 type ErrorHandler interface {
 	Type() ErrorHandlerType
-	Params() *ErrorHandlerParameters
 	Endpoint() *Endpoint
-	Ref() *string
-	Bean() *string
 	Configuration() (map[string]interface{}, error)
 }
 
-type abstractErrorHandler struct {
+type baseErrorHandler struct {
 }
 
 // Type --
-func (e abstractErrorHandler) Type() ErrorHandlerType {
-	return errorHandlerTypeAbstract
-}
-
-// Params --
-func (e abstractErrorHandler) Params() *ErrorHandlerParameters {
-	return nil
+func (e baseErrorHandler) Type() ErrorHandlerType {
+	return errorHandlerTypeBase
 }
 
 // Endpoint --
-func (e abstractErrorHandler) Endpoint() *Endpoint {
-	return nil
-}
-
-// Ref --
-func (e abstractErrorHandler) Ref() *string {
-	return nil
-}
-
-// Bean --
-func (e abstractErrorHandler) Bean() *string {
+func (e baseErrorHandler) Endpoint() *Endpoint {
 	return nil
 }
 
 // Configuration --
-func (e abstractErrorHandler) Configuration() (map[string]interface{}, error) {
+func (e baseErrorHandler) Configuration() (map[string]interface{}, error) {
 	return nil, nil
 }
 
 // ErrorHandlerNone --
 type ErrorHandlerNone struct {
-	*abstractErrorHandler
+	baseErrorHandler
 }
 
 // Type --
@@ -96,13 +86,14 @@ func (e ErrorHandlerNone) Type() ErrorHandlerType {
 // Configuration --
 func (e ErrorHandlerNone) Configuration() (map[string]interface{}, error) {
 	return map[string]interface{}{
-		errorHandlerAppPropertiesPrefix: "#class:org.apache.camel.builder.NoErrorHandlerBuilder",
+		ErrorHandlerAppPropertiesPrefix: "#class:org.apache.camel.builder.NoErrorHandlerBuilder",
+		ErrorHandlerRefName:             ErrorHandlerRefDefaultName,
 	}, nil
 }
 
 // ErrorHandlerLog represent a default (log) error handler type
 type ErrorHandlerLog struct {
-	*abstractErrorHandler
+	ErrorHandlerNone
 	Parameters *ErrorHandlerParameters `json:"parameters,omitempty"`
 }
 
@@ -111,25 +102,22 @@ func (e ErrorHandlerLog) Type() ErrorHandlerType {
 	return ErrorHandlerTypeLog
 }
 
-// Params --
-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",
+	properties, err := e.ErrorHandlerNone.Configuration()
+	if err != nil {
+		return nil, err
 	}
+	properties[ErrorHandlerAppPropertiesPrefix] = "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder"
 
-	if e.Params() != nil {
+	if e.Parameters != nil {
 		var parameters map[string]interface{}
-		err := json.Unmarshal(e.Params().RawMessage, &parameters)
+		err := json.Unmarshal(e.Parameters.RawMessage, &parameters)
 		if err != nil {
 			return nil, err
 		}
 		for key, value := range parameters {
-			properties[errorHandlerAppPropertiesPrefix+"."+key] = value
+			properties[ErrorHandlerAppPropertiesPrefix+"."+key] = value
 		}
 	}
 
@@ -138,7 +126,7 @@ func (e ErrorHandlerLog) Configuration() (map[string]interface{}, error) {
 
 // ErrorHandlerDeadLetterChannel represents a dead letter channel error handler type
 type ErrorHandlerDeadLetterChannel struct {
-	*ErrorHandlerLog
+	ErrorHandlerLog
 	DLCEndpoint *Endpoint `json:"endpoint,omitempty"`
 }
 
@@ -152,10 +140,21 @@ func (e ErrorHandlerDeadLetterChannel) Endpoint() *Endpoint {
 	return e.DLCEndpoint
 }
 
+// Configuration --
+func (e ErrorHandlerDeadLetterChannel) Configuration() (map[string]interface{}, error) {
+	properties, err := e.ErrorHandlerLog.Configuration()
+	if err != nil {
+		return nil, err
+	}
+	properties[ErrorHandlerAppPropertiesPrefix] = "#class:org.apache.camel.builder.DeadLetterChannelBuilder"
+
+	return properties, err
+}
+
 // ErrorHandlerRef represents a reference to an error handler builder available in the registry
 type ErrorHandlerRef struct {
-	*abstractErrorHandler
-	string
+	baseErrorHandler
+	v1.RawMessage
 }
 
 // Type --
@@ -163,17 +162,25 @@ func (e ErrorHandlerRef) Type() ErrorHandlerType {
 	return ErrorHandlerTypeRef
 }
 
-// Ref --
-func (e ErrorHandlerRef) Ref() *string {
-	s := string(e.string)
-	return &s
+// Configuration --
+func (e ErrorHandlerRef) Configuration() (map[string]interface{}, error) {
+	var refName string
+	err := json.Unmarshal(e.RawMessage, &refName)
+	if err != nil {
+		return nil, err
+	}
+
+	properties := map[string]interface{}{
+		ErrorHandlerRefName: refName,
+	}
+
+	return properties, nil
 }
 
 // ErrorHandlerBean represents a bean error handler type
 type ErrorHandlerBean struct {
-	*ErrorHandlerLog
-	BeanType   *string         `json:"type,omitempty"`
-	Properties *BeanProperties `json:"properties,omitempty"`
+	ErrorHandlerLog
+	BeanType *string `json:"type,omitempty"`
 }
 
 // Type --
@@ -181,16 +188,22 @@ func (e ErrorHandlerBean) Type() ErrorHandlerType {
 	return ErrorHandlerTypeBean
 }
 
-// Bean --
-func (e ErrorHandlerBean) Bean() *string {
-	return e.BeanType
+// Configuration --
+func (e ErrorHandlerBean) Configuration() (map[string]interface{}, error) {
+	properties, err := e.ErrorHandlerLog.Configuration()
+	if err != nil {
+		return nil, err
+	}
+	properties[ErrorHandlerAppPropertiesPrefix] = fmt.Sprintf("#class:%v", *e.BeanType)
+
+	return properties, err
 }
 
 // ErrorHandlerType --
 type ErrorHandlerType string
 
 const (
-	errorHandlerTypeAbstract ErrorHandlerType = ""
+	errorHandlerTypeBase ErrorHandlerType = ""
 	// ErrorHandlerTypeNone --
 	ErrorHandlerTypeNone ErrorHandlerType = "none"
 	// ErrorHandlerTypeLog --
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index d434000..45509e1 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -53,6 +53,7 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 			},
 		},
 	}
+
 	// start from the integration spec defined in the binding
 	if kameletbinding.Spec.Integration != nil {
 		it.Spec = *kameletbinding.Spec.Integration.DeepCopy()
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index 0cf95b6..0f75670 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -78,7 +78,7 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.ErrorHandler, error)
 		case v1alpha1.ErrorHandlerTypeBean:
 			dst = new(v1alpha1.ErrorHandlerBean)
 		default:
-			return nil, errors.Errorf("Unknown error type %s, supported error types are: none, log, dead-letter-channel", errHandlType)
+			return nil, errors.Errorf("Unknown error handler type %s", errHandlType)
 		}
 
 		err := json.Unmarshal(errHandlValue, dst)
@@ -89,7 +89,7 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.ErrorHandler, error)
 		return dst, nil
 	}
 
-	return nil, errors.New("You must provide any supported error handler (none, log, dead-letter-channel)")
+	return nil, errors.New("You must provide any supported error handler")
 }
 
 func setErrorHandlerConfiguration(it *v1.IntegrationSpec, errorHandlerURI string, errorHandler v1alpha1.ErrorHandler) error {
@@ -100,5 +100,8 @@ func setErrorHandlerConfiguration(it *v1.IntegrationSpec, errorHandlerURI string
 	for key, value := range properties {
 		it.AddConfiguration("property", fmt.Sprintf("%s=%v", key, value))
 	}
+	if errorHandler.Type() == v1alpha1.ErrorHandlerTypeDeadLetterChannel && errorHandlerURI != "" {
+		it.AddConfiguration("property", fmt.Sprintf("%s.deadLetterUri=%v", v1alpha1.ErrorHandlerAppPropertiesPrefix, errorHandlerURI))
+	}
 	return nil
 }
diff --git a/pkg/controller/kameletbinding/error_handler_test.go b/pkg/controller/kameletbinding/error_handler_test.go
index e05caf4..c6be802 100644
--- a/pkg/controller/kameletbinding/error_handler_test.go
+++ b/pkg/controller/kameletbinding/error_handler_test.go
@@ -18,6 +18,7 @@ limitations under the License.
 package kameletbinding
 
 import (
+	"fmt"
 	"testing"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -32,7 +33,8 @@ func TestParseErrorHandlerNoneDoesSucceed(t *testing.T) {
 	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"])
+	assert.Equal(t, "#class:org.apache.camel.builder.NoErrorHandlerBuilder", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
 }
 
 func TestParseErrorHandlerLogDoesSucceed(t *testing.T) {
@@ -43,7 +45,8 @@ func TestParseErrorHandlerLogDoesSucceed(t *testing.T) {
 	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"])
+	assert.Equal(t, "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
 }
 
 func TestParseErrorHandlerLogWithParametersDoesSucceed(t *testing.T) {
@@ -52,21 +55,27 @@ func TestParseErrorHandlerLogWithParametersDoesSucceed(t *testing.T) {
 	)
 	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, "#class:org.apache.camel.builder.DefaultErrorHandlerBuilder", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
 	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.param1"])
 	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.param2"])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
 }
 
 func TestParseErrorHandlerDLCDoesSucceed(t *testing.T) {
+	fmt.Println("Test")
 	dlcErrorHandler, err := parseErrorHandler(
 		[]byte(`{"dead-letter-channel": {"endpoint": {"uri": "someUri"}}}`),
 	)
 	assert.Nil(t, err)
+	assert.NotNil(t, dlcErrorHandler)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeDeadLetterChannel, dlcErrorHandler.Type())
 	assert.Equal(t, "someUri", *dlcErrorHandler.Endpoint().URI)
+	parameters, err := dlcErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:org.apache.camel.builder.DeadLetterChannelBuilder", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
 }
 
 func TestParseErrorHandlerDLCWithParametersDoesSucceed(t *testing.T) {
@@ -77,28 +86,49 @@ func TestParseErrorHandlerDLCWithParametersDoesSucceed(t *testing.T) {
 					"uri": "someUri"
 					}, 
 				"parameters": 
-					[{"param1": "value1"}]
+					{"param1": "value1", "param2": "value2"}
 			}
 		}`),
 	)
 	assert.Nil(t, err)
+	assert.NotNil(t, dlcErrorHandler)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeDeadLetterChannel, dlcErrorHandler.Type())
 	assert.Equal(t, "someUri", *dlcErrorHandler.Endpoint().URI)
-	assert.NotNil(t, dlcErrorHandler.Params())
+	parameters, err := dlcErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:org.apache.camel.builder.DeadLetterChannelBuilder", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
+	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.param1"])
+	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.param2"])
 }
 
-func TestParseErrorHandlerBeanWithParametersDoesSucceed(t *testing.T) {
+func TestParseErrorHandlerBeanWithParamsDoesSucceed(t *testing.T) {
 	beanErrorHandler, err := parseErrorHandler(
 		[]byte(`{
 			"bean": {
-				"type": "com.acme.MyType", 
+				"type": "com.acme.MyType",
 				"parameters": 
-					[{"param1": "value1"}]
+					{"param1": "value1", "param2": "value2"}
 			}
 		}`),
 	)
 	assert.Nil(t, err)
 	assert.Equal(t, v1alpha1.ErrorHandlerTypeBean, beanErrorHandler.Type())
-	assert.Equal(t, "com.acme.MyType", *beanErrorHandler.Bean())
-	assert.NotNil(t, beanErrorHandler.Params())
+	parameters, err := beanErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "#class:com.acme.MyType", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
+	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
+	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.param1"])
+	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.param2"])
+}
+
+func TestParseErrorHandlerRefDoesSucceed(t *testing.T) {
+	refErrorHandler, err := parseErrorHandler(
+		[]byte(`{"ref": "my-registry-ref"}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeRef, refErrorHandler.Type())
+	parameters, err := refErrorHandler.Configuration()
+	assert.Nil(t, err)
+	assert.Equal(t, "my-registry-ref", parameters[v1alpha1.ErrorHandlerRefName])
 }
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index b7a8c0d..e705e97 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -21,6 +21,7 @@ import (
 	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
 // The error-handler is a platform trait used to inject Error Handler source into the integration runtime.
@@ -50,7 +51,7 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	return e.Integration.Spec.HasDefaultErrorHandler(), nil
+	return e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName) != "", nil
 }
 
 func (t *errorHandlerTrait) Apply(e *Environment) error {
@@ -64,19 +65,20 @@ func (t *errorHandlerTrait) Apply(e *Environment) error {
 }
 
 func addErrorHandlerAsSource(e *Environment) error {
+	errorHandlerRefName := e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName)
 	// 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: `
+			Content: fmt.Sprintf(`
 			import org.apache.camel.builder.RouteBuilder;
 			public class ErrorHandlerSource extends RouteBuilder {
 			@Override
 			public void configure() throws Exception {
-				errorHandler("defaultErrorHandler");
+				errorHandler("%s");
 			  }
 			}
-			`,
+			`, errorHandlerRefName),
 		},
 		Language: v1.LanguageJavaSource,
 		Type:     v1.SourceTypeErrorHandler,
@@ -86,12 +88,3 @@ func addErrorHandlerAsSource(e *Environment) error {
 
 	return nil
 }
-
-func addErrorHandlerBeanConfiguration(e *Environment, fqn string) error {
-	// camel.beans.defaultErrorHandler = #class:the-full-qualified-class-name
-	e.Integration.Status.AddConfigurationsIfMissing(v1.ConfigurationSpec{
-		Type:  "property",
-		Value: fmt.Sprintf("camel.beans.defaultErrorHandler=#class:%s", fqn),
-	})
-	return nil
-}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 83a35a9..916b4b2 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -107,7 +107,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 			})
 		}
 		// Check if a Kamelet is configured as default error handler URI
-		defaultErrorHandlerURI := e.Integration.Spec.GetDefaultErrorHandlerURI()
+		defaultErrorHandlerURI := e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerAppPropertiesPrefix + ".deadLetterUri")
 		if defaultErrorHandlerURI != "" {
 			if strings.HasPrefix(defaultErrorHandlerURI, "kamelet:") {
 				kamelets = append(kamelets, extractKamelet(defaultErrorHandlerURI))
@@ -124,16 +124,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
-<<<<<<< HEAD
-<<<<<<< HEAD
-
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseRunning) {
-=======
-=======
-
->>>>>>> refactor(trait): error handler kamelet
-	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
->>>>>>> refactor(trait): integration error handler spec
 		if err := t.addKamelets(e); err != nil {
 			return err
 		}

[camel-k] 03/30: fix(kamelets): optional error handler

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit a488a3abf8f10ffe741b188401eb7f7e5c17202b
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Mar 16 17:38:14 2021 +0100

    fix(kamelets): optional error handler
---
 pkg/controller/kameletbinding/common.go | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 354dfa2..32d7182 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -79,9 +79,12 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
-	onError, err := bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
-	if err != nil {
-		return nil, errors.Wrap(err, "could not determine error handler URI")
+	var onError *bindings.Binding
+	if kameletbinding.Spec.ErrorHandler.Ref != nil || kameletbinding.Spec.ErrorHandler.URI != nil {
+		onError, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not determine error handler URI")
+		}
 	}
 
 	steps := make([]*bindings.Binding, 0, len(kameletbinding.Spec.Steps))

[camel-k] 13/30: feat(trait): error handler advanced configuration

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 647b82fba4866709c225a17b3d7a0300c26f14b2
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 17:09:24 2021 +0200

    feat(trait): error handler advanced configuration
---
 .../kamelet-binding-error-handler.yaml             |  5 +++-
 pkg/controller/kameletbinding/common.go            |  3 ++-
 pkg/resources/resources.go                         |  4 +--
 pkg/trait/error_handler.go                         | 30 ++++++++++++++++++----
 4 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index ae8eb78..457b173 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -38,5 +38,8 @@ spec:
         apiVersion: camel.apache.org/v1alpha1
         name: error-handler
       properties:
-        message: "ERROR!"   
+        message: "ERROR!"
+    configuration:
+      maximumRedeliveries: 3
+      redeliveryDelay: 2000
     
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 06b5b76..c4d4641 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -166,7 +166,8 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 
 func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandlerURI string, errorHandlerSpec v1alpha1.ErrorHandler) error {
 	it.ErrorHandler = v1.ErrorHandlerSpec{
-		Type: string(errorHandlerSpec.Type),
+		Type:          string(errorHandlerSpec.Type),
+		Configuration: &v1.ErrorHandlerConfiguration{errorHandlerSpec.Configuration.RawMessage},
 	}
 
 	if errorHandlerURI != "" {
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 7603bbb..6b712ac 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -113,9 +113,9 @@ var assets = func() http.FileSystem {
 		"/crd/bases/camel.apache.org_kameletbindings.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kameletbindings.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 68634,
+			uncompressedSize: 55181,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\xff\x6f\xdb\x38\xb2\xff\x3d\x7f\xc5\x20\x39\xa0\x2d\x10\xd9\x71\x92\x76\x77\xfd\x7e\x28\xb2\xc9\xf6\xce\xaf\xdd\x34\xc8\x97\x3b\xdc\x6b\x7b\x00\x2d\x8d\x6d\x5e\x24\x52\x47\x52\x71\xfc\xb6\xfd\xdf\x1f\x48\x4a\xb2\xfc\x45\x12\xe5\xd8\xdd\xf4\x41\x04\x8a\xc6\x16\x35\x9c\x19\x0e\x87\xdf\xe6\x33\x3e\x00\x6f\x7b\x65\xef\x00\x3e\x50\x1f\x99\xc4\x00\x14\x07\x35\x41\x38\x8b\x89\x3f\x41\xb8\xe1\x23\x35\x25\x02\xe1\x1d\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x01\x4b\x8e\xe3\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\x7b\x7e\xed\xa6\x45\x92\xde\xe1\x5e\xdb\x03\x68\x69\x6c\xf3\x22\x91\x3a\x92\x8a\xe3\xef\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x99\x72\xec\x6e\x0a\x88\xc0\x62\x6b\x8b\x1a\xce\x0c\x87\xc3\x99\x21\x3f\xce\x11\x78\xbb\x6b\x07\x47\xf0\x9e\x06\xc8\x24\x86\xa0\x38\xa8\x29\xc2\x59\x42\x82\x29\xc2\x35\x1f\xab\x19\x11\x08\x [...]
 		},
 		"/crd/bases/camel.apache.org_kamelets.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kamelets.yaml",
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index ef93d67..2b57738 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -18,6 +18,7 @@ limitations under the License.
 package trait
 
 import (
+	"encoding/json"
 	"fmt"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
@@ -67,7 +68,7 @@ func (t *errorHandlerTrait) Apply(e *Environment) error {
 }
 
 func addErrorHandlerAsSource(e *Environment) error {
-	errorHandlerStatement, err := parseErrorHandler(e.Integration.Spec.ErrorHandler.URI, e.Integration.Spec.ErrorHandler.Type)
+	errorHandlerStatement, err := parseErrorHandler(e.Integration.Spec.ErrorHandler)
 	if err != nil {
 		return err
 	}
@@ -104,15 +105,34 @@ func addErrorHandlerAsSource(e *Environment) error {
 	return nil
 }
 
-func parseErrorHandler(errHandlURI string, errHandlType string) (string, error) {
-	switch errHandlType {
+func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
+	switch errorHandlerSpec.Type {
 	case "no":
 		return `errorHandler(noErrorHandler());`, nil
 	case "default":
 		return `errorHandler(defaultErrorHandler());`, nil
 	case "dead-letter-channel":
-		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v"));`, errHandlURI), nil
+		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Configuration)
+		if err != nil {
+			return "", err
+		}
+
+		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v")%v);`, errorHandlerSpec.URI, errorHandlerConfiguration), nil
+	}
+
+	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errorHandlerSpec.Type)
+}
+
+func parseErrorHandlerConfiguration(conf *v1.ErrorHandlerConfiguration) (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 "", fmt.Errorf("Cannot recognize any error handler of type %s", errHandlType)
+	return javaPropertiesBuilder, nil
 }

[camel-k] 24/30: refactor(controller): error handler bean properties

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 987fc9da7c1f0166ba29142d24fe2044b21aa735
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 11:09:04 2021 +0200

    refactor(controller): error handler bean properties
---
 .../error-handler/kamelet-binding-error-handler.yaml   |  2 +-
 pkg/apis/camel/v1alpha1/error_handler_types.go         | 18 +++++++++++++++---
 pkg/controller/kameletbinding/error_handler_test.go    |  8 ++++----
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index 6c44ca7..7a935d6 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -38,7 +38,7 @@ spec:
 #    ref: "something"
 #    bean:
 #      type: "org.apache.camel.builder.DeadLetterChannelBuilder"
-#      parameters:
+#      properties:
 #        deadLetterUri: log:error
     dead-letter-channel:
       endpoint:
diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index 4f3f4e7..5019796 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -179,8 +179,9 @@ func (e ErrorHandlerRef) Configuration() (map[string]interface{}, error) {
 
 // ErrorHandlerBean represents a bean error handler type
 type ErrorHandlerBean struct {
-	ErrorHandlerLog
-	BeanType *string `json:"type,omitempty"`
+	ErrorHandlerNone
+	BeanType       *string         `json:"type,omitempty"`
+	BeanProperties *BeanProperties `json:"properties,omitempty"`
 }
 
 // Type --
@@ -190,12 +191,23 @@ func (e ErrorHandlerBean) Type() ErrorHandlerType {
 
 // Configuration --
 func (e ErrorHandlerBean) Configuration() (map[string]interface{}, error) {
-	properties, err := e.ErrorHandlerLog.Configuration()
+	properties, err := e.ErrorHandlerNone.Configuration()
 	if err != nil {
 		return nil, err
 	}
 	properties[ErrorHandlerAppPropertiesPrefix] = fmt.Sprintf("#class:%v", *e.BeanType)
 
+	if e.BeanProperties != nil {
+		var beanProperties map[string]interface{}
+		err := json.Unmarshal(e.BeanProperties.RawMessage, &beanProperties)
+		if err != nil {
+			return nil, err
+		}
+		for key, value := range beanProperties {
+			properties[ErrorHandlerAppPropertiesPrefix+"."+key] = value
+		}
+	}
+
 	return properties, err
 }
 
diff --git a/pkg/controller/kameletbinding/error_handler_test.go b/pkg/controller/kameletbinding/error_handler_test.go
index c6be802..94e6643 100644
--- a/pkg/controller/kameletbinding/error_handler_test.go
+++ b/pkg/controller/kameletbinding/error_handler_test.go
@@ -107,8 +107,8 @@ func TestParseErrorHandlerBeanWithParamsDoesSucceed(t *testing.T) {
 		[]byte(`{
 			"bean": {
 				"type": "com.acme.MyType",
-				"parameters": 
-					{"param1": "value1", "param2": "value2"}
+				"properties": 
+					{"beanProp1": "value1", "beanProp2": "value2"}
 			}
 		}`),
 	)
@@ -118,8 +118,8 @@ func TestParseErrorHandlerBeanWithParamsDoesSucceed(t *testing.T) {
 	assert.Nil(t, err)
 	assert.Equal(t, "#class:com.acme.MyType", parameters[v1alpha1.ErrorHandlerAppPropertiesPrefix])
 	assert.Equal(t, v1alpha1.ErrorHandlerRefDefaultName, parameters[v1alpha1.ErrorHandlerRefName])
-	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.param1"])
-	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.param2"])
+	assert.Equal(t, "value1", parameters["camel.beans.defaultErrorHandler.beanProp1"])
+	assert.Equal(t, "value2", parameters["camel.beans.defaultErrorHandler.beanProp2"])
 }
 
 func TestParseErrorHandlerRefDoesSucceed(t *testing.T) {

[camel-k] 14/30: fix(trait): default error handler configuration setting

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 68aaeb4ec4e3dc4721e10289e9426b9a5b23b699
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 17:25:41 2021 +0200

    fix(trait): default error handler configuration setting
---
 pkg/trait/error_handler.go | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index 2b57738..eadaa70 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -110,7 +110,12 @@ func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
 	case "no":
 		return `errorHandler(noErrorHandler());`, nil
 	case "default":
-		return `errorHandler(defaultErrorHandler());`, nil
+		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Configuration)
+		if err != nil {
+			return "", err
+		}
+
+		return fmt.Sprintf(`errorHandler(defaultErrorHandler()%v);`, errorHandlerConfiguration), nil
 	case "dead-letter-channel":
 		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Configuration)
 		if err != nil {

[camel-k] 28/30: chore(trait): polishing PR

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 82df277aa82431a0ba26188c635ce65ce4567ff2
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 17:19:00 2021 +0200

    chore(trait): polishing PR
---
 .../camel-k-dev/1.4.0/camel.apache.org_integrations.yaml  | 15 ---------------
 deploy/traits.yaml                                        |  2 +-
 docs/modules/traits/pages/error-handler.adoc              |  2 +-
 .../kamelets/error-handler/error-handler.kamelet.yaml     |  3 +--
 .../error-handler/incremental-id-source.kamelet.yaml      |  2 +-
 pkg/apis/camel/v1/integration_types_support.go            |  2 +-
 pkg/trait/error_handler.go                                |  2 +-
 7 files changed, 6 insertions(+), 22 deletions(-)

diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
index 0b1b88a..96e26b9 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
@@ -88,21 +88,6 @@ spec:
                 items:
                   type: string
                 type: array
-              errorHandler:
-                description: ErrorHandlerSpec respresents an integration error handler
-                  to be used as default at runtime
-                properties:
-                  parameters:
-                    description: ErrorHandlerParameters is an unstructured object
-                      representing the configuration parameters available for an error
-                      handler
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  type:
-                    type: string
-                  uri:
-                    type: string
-                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index 22cc617..b2c3af3 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -284,7 +284,7 @@ traits:
     type: bool
     description: Can be used to enable or disable a trait. All traits share this common
       property.
-  - name: ',omitempty'
+  - name: error-handler-ref
     type: string
     description: The error handler ref name found in application properties
 - name: gc
diff --git a/docs/modules/traits/pages/error-handler.adoc b/docs/modules/traits/pages/error-handler.adoc
index 149eaee..978e76f 100755
--- a/docs/modules/traits/pages/error-handler.adoc
+++ b/docs/modules/traits/pages/error-handler.adoc
@@ -27,7 +27,7 @@ The following configuration options are available:
 | bool
 | Can be used to enable or disable a trait. All traits share this common property.
 
-| error-handler.,omitempty
+| error-handler.error-handler-ref
 | string
 | The error handler ref name found in application properties
 
diff --git a/examples/kamelets/error-handler/error-handler.kamelet.yaml b/examples/kamelets/error-handler/error-handler.kamelet.yaml
index 9ace959..a5aa060 100644
--- a/examples/kamelets/error-handler/error-handler.kamelet.yaml
+++ b/examples/kamelets/error-handler/error-handler.kamelet.yaml
@@ -22,7 +22,7 @@ metadata:
 spec:
   definition:
     title: "Error Log Sink"
-    description: "Consume events from a channel"
+    description: "Error logger channel"
     required:
       - message
     properties:
@@ -35,7 +35,6 @@ spec:
     from:
       uri: kamelet:source
       steps:
-#      - to: my-dlc
       - set-body:
           constant: "{{message}}"
       - to: "log:error-sink"  
diff --git a/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml b/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
index 5e3181b..ee475da 100644
--- a/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
+++ b/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
@@ -24,7 +24,7 @@ metadata:
 spec:
   definition:
     title: "Incremental ID Source"
-    description: "Produces periodic events with an incremental ID"
+    description: "Produces periodic events with an incremental ID and fails when the ID contains any 0 character"
     properties:
       period:
         title: Period
diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go
index 6efdc24..f7e505e 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -136,7 +136,7 @@ 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 {
+			if len(splitConf) > 1 {
 				return splitConf[1]
 			}
 		}
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index dd6e218..a72a94a 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -29,7 +29,7 @@ import (
 type errorHandlerTrait struct {
 	BaseTrait `property:",squash"`
 	// The error handler ref name found in application properties
-	ErrorHandlerRef string `property:",omitempty"`
+	ErrorHandlerRef string `property:"error-handler-ref" json:"error-handler-ref,omitempty"`
 }
 
 func newErrorHandlerTrait() Trait {

[camel-k] 15/30: refactor(trait): error handler spec definition

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 92d1c5db4d102ecdf26341121d83156372136169
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Thu Apr 22 15:57:40 2021 +0200

    refactor(trait): error handler spec definition
---
 .../crd/bases/camel.apache.org_integrations.yaml   |   6 +-
 .../bases/camel.apache.org_kameletbindings.yaml    | 231 +--------------------
 .../1.4.0/camel.apache.org_integrations.yaml       |   6 +-
 .../1.4.0/camel.apache.org_kameletbindings.yaml    | 231 +--------------------
 .../kamelet-binding-error-handler.yaml             |  22 +-
 examples/kamelets/error-handler/readme.md          |  23 +-
 helm/camel-k/crds/crd-integration.yaml             |   6 +-
 helm/camel-k/crds/crd-kamelet-binding.yaml         | 231 +--------------------
 pkg/apis/camel/v1/common_types.go                  |  10 +-
 pkg/apis/camel/v1alpha1/error_handler_types.go     | 111 ++++++++++
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |  14 --
 pkg/controller/kameletbinding/common.go            |  33 +--
 pkg/controller/kameletbinding/error_handler.go     | 102 +++++++++
 pkg/trait/error_handler.go                         |  10 +-
 14 files changed, 278 insertions(+), 758 deletions(-)

diff --git a/config/crd/bases/camel.apache.org_integrations.yaml b/config/crd/bases/camel.apache.org_integrations.yaml
index c838f1f..0b1b88a 100644
--- a/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/config/crd/bases/camel.apache.org_integrations.yaml
@@ -92,8 +92,10 @@ spec:
                 description: ErrorHandlerSpec respresents an integration error handler
                   to be used as default at runtime
                 properties:
-                  configuration:
-                    description: ErrorHandlerConfiguration --
+                  parameters:
+                    description: ErrorHandlerParameters is an unstructured object
+                      representing the configuration parameters available for an error
+                      handler
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                   type:
diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index 046549c..2b78d2f 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -66,231 +66,8 @@ spec:
               errorHandler:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
-                properties:
-                  configuration:
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  endpoint:
-                    description: Endpoint represents a source/sink external entity
-                    properties:
-                      properties:
-                        description: Properties are a key value representation of
-                          endpoint properties
-                        type: object
-                        x-kubernetes-preserve-unknown-fields: true
-                      ref:
-                        description: Ref can be used to declare a Kubernetes resource
-                          as source/sink endpoint
-                        properties:
-                          apiVersion:
-                            description: API version of the referent.
-                            type: string
-                          fieldPath:
-                            description: 'If referring to a piece of an object instead
-                              of an entire object, this string should contain a valid
-                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                              For example, if the object reference is to a container
-                              within a pod, this would take on a value like: "spec.containers{name}"
-                              (where "name" refers to the name of the container that
-                              triggered the event) or if no container name is specified
-                              "spec.containers[2]" (container with index 2 in this
-                              pod). This syntax is chosen only to have some well-defined
-                              way of referencing a part of an object. TODO: this design
-                              is not final and this field is subject to change in
-                              the future.'
-                            type: string
-                          kind:
-                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                            type: string
-                          name:
-                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                            type: string
-                          namespace:
-                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                            type: string
-                          resourceVersion:
-                            description: 'Specific resourceVersion to which this reference
-                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                            type: string
-                          uid:
-                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                            type: string
-                        type: object
-                      types:
-                        additionalProperties:
-                          properties:
-                            mediaType:
-                              type: string
-                            schema:
-                              description: JSONSchemaProps is a JSON-Schema following
-                                Specification Draft 4 (http://json-schema.org/).
-                              properties:
-                                $schema:
-                                  description: JSONSchemaURL represents a schema url.
-                                  type: string
-                                description:
-                                  type: string
-                                example:
-                                  description: 'JSON represents any valid JSON value.
-                                    These types are supported: bool, int64, float64,
-                                    string, []interface{}, map[string]interface{}
-                                    and nil.'
-                                  x-kubernetes-preserve-unknown-fields: true
-                                externalDocs:
-                                  description: ExternalDocumentation allows referencing
-                                    an external resource for extended documentation.
-                                  properties:
-                                    description:
-                                      type: string
-                                    url:
-                                      type: string
-                                  type: object
-                                id:
-                                  type: string
-                                properties:
-                                  additionalProperties:
-                                    properties:
-                                      default:
-                                        description: default is a default value for
-                                          undefined object fields.
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      description:
-                                        type: string
-                                      enum:
-                                        items:
-                                          description: 'JSON represents any valid
-                                            JSON value. These types are supported:
-                                            bool, int64, float64, string, []interface{},
-                                            map[string]interface{} and nil.'
-                                          x-kubernetes-preserve-unknown-fields: true
-                                        type: array
-                                      example:
-                                        description: 'JSON represents any valid JSON
-                                          value. These types are supported: bool,
-                                          int64, float64, string, []interface{}, map[string]interface{}
-                                          and nil.'
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      exclusiveMaximum:
-                                        type: boolean
-                                      exclusiveMinimum:
-                                        type: boolean
-                                      format:
-                                        description: "format is an OpenAPI v3 format
-                                          string. Unknown formats are ignored. The
-                                          following formats are validated: \n - bsonobjectid:
-                                          a bson object ID, i.e. a 24 characters hex
-                                          string - uri: an URI as parsed by Golang
-                                          net/url.ParseRequestURI - email: an email
-                                          address as parsed by Golang net/mail.ParseAddress
-                                          - hostname: a valid representation for an
-                                          Internet host name, as defined by RFC 1034,
-                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
-                                          as parsed by Golang net.ParseIP - ipv6:
-                                          an IPv6 IP as parsed by Golang net.ParseIP
-                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
-                                          - mac: a MAC address as parsed by Golang
-                                          net.ParseMAC - uuid: an UUID that allows
-                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid3: an UUID3 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid4: an UUID4 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - uuid5: an UUID5 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - isbn: an ISBN10 or ISBN13 number string
-                                          like \"0321751043\" or \"978-0321751041\"
-                                          - isbn10: an ISBN10 number string like \"0321751043\"
-                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                          - creditcard: a credit card number defined
-                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                          with any non digit characters mixed in -
-                                          ssn: a U.S. social security number following
-                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
-                                          - hexcolor: an hexadecimal color code like
-                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                          - rgbcolor: an RGB color code like rgb like
-                                          \"rgb(255,255,2559\" - byte: base64 encoded
-                                          binary data - password: any kind of string
-                                          - date: a date string like \"2006-01-02\"
-                                          as defined by full-date in RFC3339 - duration:
-                                          a duration string like \"22 ns\" as parsed
-                                          by Golang time.ParseDuration or compatible
-                                          with Scala duration format - datetime: a
-                                          date time string like \"2014-12-15T19:30:20.000Z\"
-                                          as defined by date-time in RFC3339."
-                                        type: string
-                                      id:
-                                        type: string
-                                      maxItems:
-                                        format: int64
-                                        type: integer
-                                      maxLength:
-                                        format: int64
-                                        type: integer
-                                      maxProperties:
-                                        format: int64
-                                        type: integer
-                                      maximum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      minItems:
-                                        format: int64
-                                        type: integer
-                                      minLength:
-                                        format: int64
-                                        type: integer
-                                      minProperties:
-                                        format: int64
-                                        type: integer
-                                      minimum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      multipleOf:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      nullable:
-                                        type: boolean
-                                      pattern:
-                                        type: string
-                                      title:
-                                        type: string
-                                      type:
-                                        type: string
-                                      uniqueItems:
-                                        type: boolean
-                                      x-descriptors:
-                                        description: The list of descriptors that
-                                          determine which UI components to use on
-                                          different views
-                                        items:
-                                          type: string
-                                        type: array
-                                    type: object
-                                  type: object
-                                required:
-                                  items:
-                                    type: string
-                                  type: array
-                                title:
-                                  type: string
-                                type:
-                                  type: string
-                              type: object
-                          type: object
-                        description: Types defines the schema of the data produced/consumed
-                          by the endpoint
-                        type: object
-                      uri:
-                        description: URI can alternatively be used to specify the
-                          (Camel) endpoint explicitly
-                        type: string
-                    type: object
-                  type:
-                    type: string
                 type: object
+                x-kubernetes-preserve-unknown-fields: true
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
@@ -316,8 +93,10 @@ spec:
                     description: ErrorHandlerSpec respresents an integration error
                       handler to be used as default at runtime
                     properties:
-                      configuration:
-                        description: ErrorHandlerConfiguration --
+                      parameters:
+                        description: ErrorHandlerParameters is an unstructured object
+                          representing the configuration parameters available for
+                          an error handler
                         type: object
                         x-kubernetes-preserve-unknown-fields: true
                       type:
diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
index c838f1f..0b1b88a 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
@@ -92,8 +92,10 @@ spec:
                 description: ErrorHandlerSpec respresents an integration error handler
                   to be used as default at runtime
                 properties:
-                  configuration:
-                    description: ErrorHandlerConfiguration --
+                  parameters:
+                    description: ErrorHandlerParameters is an unstructured object
+                      representing the configuration parameters available for an error
+                      handler
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                   type:
diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
index 046549c..2b78d2f 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
@@ -66,231 +66,8 @@ spec:
               errorHandler:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
-                properties:
-                  configuration:
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  endpoint:
-                    description: Endpoint represents a source/sink external entity
-                    properties:
-                      properties:
-                        description: Properties are a key value representation of
-                          endpoint properties
-                        type: object
-                        x-kubernetes-preserve-unknown-fields: true
-                      ref:
-                        description: Ref can be used to declare a Kubernetes resource
-                          as source/sink endpoint
-                        properties:
-                          apiVersion:
-                            description: API version of the referent.
-                            type: string
-                          fieldPath:
-                            description: 'If referring to a piece of an object instead
-                              of an entire object, this string should contain a valid
-                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                              For example, if the object reference is to a container
-                              within a pod, this would take on a value like: "spec.containers{name}"
-                              (where "name" refers to the name of the container that
-                              triggered the event) or if no container name is specified
-                              "spec.containers[2]" (container with index 2 in this
-                              pod). This syntax is chosen only to have some well-defined
-                              way of referencing a part of an object. TODO: this design
-                              is not final and this field is subject to change in
-                              the future.'
-                            type: string
-                          kind:
-                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                            type: string
-                          name:
-                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                            type: string
-                          namespace:
-                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                            type: string
-                          resourceVersion:
-                            description: 'Specific resourceVersion to which this reference
-                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                            type: string
-                          uid:
-                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                            type: string
-                        type: object
-                      types:
-                        additionalProperties:
-                          properties:
-                            mediaType:
-                              type: string
-                            schema:
-                              description: JSONSchemaProps is a JSON-Schema following
-                                Specification Draft 4 (http://json-schema.org/).
-                              properties:
-                                $schema:
-                                  description: JSONSchemaURL represents a schema url.
-                                  type: string
-                                description:
-                                  type: string
-                                example:
-                                  description: 'JSON represents any valid JSON value.
-                                    These types are supported: bool, int64, float64,
-                                    string, []interface{}, map[string]interface{}
-                                    and nil.'
-                                  x-kubernetes-preserve-unknown-fields: true
-                                externalDocs:
-                                  description: ExternalDocumentation allows referencing
-                                    an external resource for extended documentation.
-                                  properties:
-                                    description:
-                                      type: string
-                                    url:
-                                      type: string
-                                  type: object
-                                id:
-                                  type: string
-                                properties:
-                                  additionalProperties:
-                                    properties:
-                                      default:
-                                        description: default is a default value for
-                                          undefined object fields.
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      description:
-                                        type: string
-                                      enum:
-                                        items:
-                                          description: 'JSON represents any valid
-                                            JSON value. These types are supported:
-                                            bool, int64, float64, string, []interface{},
-                                            map[string]interface{} and nil.'
-                                          x-kubernetes-preserve-unknown-fields: true
-                                        type: array
-                                      example:
-                                        description: 'JSON represents any valid JSON
-                                          value. These types are supported: bool,
-                                          int64, float64, string, []interface{}, map[string]interface{}
-                                          and nil.'
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      exclusiveMaximum:
-                                        type: boolean
-                                      exclusiveMinimum:
-                                        type: boolean
-                                      format:
-                                        description: "format is an OpenAPI v3 format
-                                          string. Unknown formats are ignored. The
-                                          following formats are validated: \n - bsonobjectid:
-                                          a bson object ID, i.e. a 24 characters hex
-                                          string - uri: an URI as parsed by Golang
-                                          net/url.ParseRequestURI - email: an email
-                                          address as parsed by Golang net/mail.ParseAddress
-                                          - hostname: a valid representation for an
-                                          Internet host name, as defined by RFC 1034,
-                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
-                                          as parsed by Golang net.ParseIP - ipv6:
-                                          an IPv6 IP as parsed by Golang net.ParseIP
-                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
-                                          - mac: a MAC address as parsed by Golang
-                                          net.ParseMAC - uuid: an UUID that allows
-                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid3: an UUID3 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid4: an UUID4 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - uuid5: an UUID5 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - isbn: an ISBN10 or ISBN13 number string
-                                          like \"0321751043\" or \"978-0321751041\"
-                                          - isbn10: an ISBN10 number string like \"0321751043\"
-                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                          - creditcard: a credit card number defined
-                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                          with any non digit characters mixed in -
-                                          ssn: a U.S. social security number following
-                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
-                                          - hexcolor: an hexadecimal color code like
-                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                          - rgbcolor: an RGB color code like rgb like
-                                          \"rgb(255,255,2559\" - byte: base64 encoded
-                                          binary data - password: any kind of string
-                                          - date: a date string like \"2006-01-02\"
-                                          as defined by full-date in RFC3339 - duration:
-                                          a duration string like \"22 ns\" as parsed
-                                          by Golang time.ParseDuration or compatible
-                                          with Scala duration format - datetime: a
-                                          date time string like \"2014-12-15T19:30:20.000Z\"
-                                          as defined by date-time in RFC3339."
-                                        type: string
-                                      id:
-                                        type: string
-                                      maxItems:
-                                        format: int64
-                                        type: integer
-                                      maxLength:
-                                        format: int64
-                                        type: integer
-                                      maxProperties:
-                                        format: int64
-                                        type: integer
-                                      maximum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      minItems:
-                                        format: int64
-                                        type: integer
-                                      minLength:
-                                        format: int64
-                                        type: integer
-                                      minProperties:
-                                        format: int64
-                                        type: integer
-                                      minimum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      multipleOf:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      nullable:
-                                        type: boolean
-                                      pattern:
-                                        type: string
-                                      title:
-                                        type: string
-                                      type:
-                                        type: string
-                                      uniqueItems:
-                                        type: boolean
-                                      x-descriptors:
-                                        description: The list of descriptors that
-                                          determine which UI components to use on
-                                          different views
-                                        items:
-                                          type: string
-                                        type: array
-                                    type: object
-                                  type: object
-                                required:
-                                  items:
-                                    type: string
-                                  type: array
-                                title:
-                                  type: string
-                                type:
-                                  type: string
-                              type: object
-                          type: object
-                        description: Types defines the schema of the data produced/consumed
-                          by the endpoint
-                        type: object
-                      uri:
-                        description: URI can alternatively be used to specify the
-                          (Camel) endpoint explicitly
-                        type: string
-                    type: object
-                  type:
-                    type: string
                 type: object
+                x-kubernetes-preserve-unknown-fields: true
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
@@ -316,8 +93,10 @@ spec:
                     description: ErrorHandlerSpec respresents an integration error
                       handler to be used as default at runtime
                     properties:
-                      configuration:
-                        description: ErrorHandlerConfiguration --
+                      parameters:
+                        description: ErrorHandlerParameters is an unstructured object
+                          representing the configuration parameters available for
+                          an error handler
                         type: object
                         x-kubernetes-preserve-unknown-fields: true
                       type:
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index 457b173..5f62adc 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -31,15 +31,15 @@ spec:
       apiVersion: camel.apache.org/v1alpha1
       name: log-sink
   errorHandler:
-    type: dead-letter-channel
-    endpoint:
-      ref:
-        kind: Kamelet
-        apiVersion: camel.apache.org/v1alpha1
-        name: error-handler
-      properties:
-        message: "ERROR!"
-    configuration:
-      maximumRedeliveries: 3
-      redeliveryDelay: 2000
+    dead-letter-channel:
+      endpoint:
+        ref:
+          kind: Kamelet
+          apiVersion: camel.apache.org/v1alpha1
+          name: error-handler
+        properties:
+          message: "ERROR!"
+      parameters:
+        maximumRedeliveries: 3
+        redeliveryDelay: 2000    
     
diff --git a/examples/kamelets/error-handler/readme.md b/examples/kamelets/error-handler/readme.md
index dc4d75b..42293cd 100644
--- a/examples/kamelets/error-handler/readme.md
+++ b/examples/kamelets/error-handler/readme.md
@@ -41,18 +41,21 @@ log-sink                Ready
 incremental-id-source   Ready
 ```
 ## Error Handler Kamelet Binding
-We can create a `KameletBinding` which is started by the _incremental-id-source_ `Kamelet` and log events to _log-sink_ `Kamelet`. As this will sporadically fail, we can configure an _errorHandler_ with the _error-handler_ `Kamelet` as **Dead Letter Channel**. We can declare it as in `kamelet-binding-error-handler.yaml` file:
+We can create a `KameletBinding` which is started by the _incremental-id-source_ `Kamelet` and log events to _log-sink_ `Kamelet`. As this will sporadically fail, we can configure an _errorHandler_ with the _error-handler_ `Kamelet` as **Dead Letter Channel**. We want to configure also some redelivery policies. We can declare it as in `kamelet-binding-error-handler.yaml` file:
 ```
 ...
   errorHandler:
-    type: dead-letter-channel
-    endpoint:
-      ref:
-        kind: Kamelet
-        apiVersion: camel.apache.org/v1alpha1
-        name: error-handler
-      properties:
-        message: "ERROR!"
+    dead-letter-channel:
+      endpoint:
+        ref:
+          kind: Kamelet
+          apiVersion: camel.apache.org/v1alpha1
+          name: error-handler
+        properties:
+          message: "ERROR!"
+      parameters:
+        maximumRedeliveries: 3
+        redeliveryDelay: 2000
 ```
 Execute the following command to start the `Integration`:
 ```
@@ -63,6 +66,6 @@ As soon as the `Integration` starts, it will log the events on the `ok` log chan
 [1] 2021-04-21 13:03:43,773 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #8]
 [1] 2021-04-21 13:03:44,774 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #9]
 [1] 2021-04-21 13:03:45,898 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR!]
-[1] 2021-04-21 13:03:46,775 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #11]
+[1] 2021-04-21 13:09:46,775 INFO  [sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #11]
 ```
 This example is useful to guide you through the configuration of an error handler. In a production environment you will likely configure the error handler `Kamelet` pointing to a persistent queue.
\ No newline at end of file
diff --git a/helm/camel-k/crds/crd-integration.yaml b/helm/camel-k/crds/crd-integration.yaml
index c838f1f..0b1b88a 100644
--- a/helm/camel-k/crds/crd-integration.yaml
+++ b/helm/camel-k/crds/crd-integration.yaml
@@ -92,8 +92,10 @@ spec:
                 description: ErrorHandlerSpec respresents an integration error handler
                   to be used as default at runtime
                 properties:
-                  configuration:
-                    description: ErrorHandlerConfiguration --
+                  parameters:
+                    description: ErrorHandlerParameters is an unstructured object
+                      representing the configuration parameters available for an error
+                      handler
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                   type:
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index 046549c..2b78d2f 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -66,231 +66,8 @@ spec:
               errorHandler:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
-                properties:
-                  configuration:
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  endpoint:
-                    description: Endpoint represents a source/sink external entity
-                    properties:
-                      properties:
-                        description: Properties are a key value representation of
-                          endpoint properties
-                        type: object
-                        x-kubernetes-preserve-unknown-fields: true
-                      ref:
-                        description: Ref can be used to declare a Kubernetes resource
-                          as source/sink endpoint
-                        properties:
-                          apiVersion:
-                            description: API version of the referent.
-                            type: string
-                          fieldPath:
-                            description: 'If referring to a piece of an object instead
-                              of an entire object, this string should contain a valid
-                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                              For example, if the object reference is to a container
-                              within a pod, this would take on a value like: "spec.containers{name}"
-                              (where "name" refers to the name of the container that
-                              triggered the event) or if no container name is specified
-                              "spec.containers[2]" (container with index 2 in this
-                              pod). This syntax is chosen only to have some well-defined
-                              way of referencing a part of an object. TODO: this design
-                              is not final and this field is subject to change in
-                              the future.'
-                            type: string
-                          kind:
-                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                            type: string
-                          name:
-                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                            type: string
-                          namespace:
-                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                            type: string
-                          resourceVersion:
-                            description: 'Specific resourceVersion to which this reference
-                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                            type: string
-                          uid:
-                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                            type: string
-                        type: object
-                      types:
-                        additionalProperties:
-                          properties:
-                            mediaType:
-                              type: string
-                            schema:
-                              description: JSONSchemaProps is a JSON-Schema following
-                                Specification Draft 4 (http://json-schema.org/).
-                              properties:
-                                $schema:
-                                  description: JSONSchemaURL represents a schema url.
-                                  type: string
-                                description:
-                                  type: string
-                                example:
-                                  description: 'JSON represents any valid JSON value.
-                                    These types are supported: bool, int64, float64,
-                                    string, []interface{}, map[string]interface{}
-                                    and nil.'
-                                  x-kubernetes-preserve-unknown-fields: true
-                                externalDocs:
-                                  description: ExternalDocumentation allows referencing
-                                    an external resource for extended documentation.
-                                  properties:
-                                    description:
-                                      type: string
-                                    url:
-                                      type: string
-                                  type: object
-                                id:
-                                  type: string
-                                properties:
-                                  additionalProperties:
-                                    properties:
-                                      default:
-                                        description: default is a default value for
-                                          undefined object fields.
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      description:
-                                        type: string
-                                      enum:
-                                        items:
-                                          description: 'JSON represents any valid
-                                            JSON value. These types are supported:
-                                            bool, int64, float64, string, []interface{},
-                                            map[string]interface{} and nil.'
-                                          x-kubernetes-preserve-unknown-fields: true
-                                        type: array
-                                      example:
-                                        description: 'JSON represents any valid JSON
-                                          value. These types are supported: bool,
-                                          int64, float64, string, []interface{}, map[string]interface{}
-                                          and nil.'
-                                        x-kubernetes-preserve-unknown-fields: true
-                                      exclusiveMaximum:
-                                        type: boolean
-                                      exclusiveMinimum:
-                                        type: boolean
-                                      format:
-                                        description: "format is an OpenAPI v3 format
-                                          string. Unknown formats are ignored. The
-                                          following formats are validated: \n - bsonobjectid:
-                                          a bson object ID, i.e. a 24 characters hex
-                                          string - uri: an URI as parsed by Golang
-                                          net/url.ParseRequestURI - email: an email
-                                          address as parsed by Golang net/mail.ParseAddress
-                                          - hostname: a valid representation for an
-                                          Internet host name, as defined by RFC 1034,
-                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
-                                          as parsed by Golang net.ParseIP - ipv6:
-                                          an IPv6 IP as parsed by Golang net.ParseIP
-                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
-                                          - mac: a MAC address as parsed by Golang
-                                          net.ParseMAC - uuid: an UUID that allows
-                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid3: an UUID3 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                          - uuid4: an UUID4 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - uuid5: an UUID5 that allows uppercase
-                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                          - isbn: an ISBN10 or ISBN13 number string
-                                          like \"0321751043\" or \"978-0321751041\"
-                                          - isbn10: an ISBN10 number string like \"0321751043\"
-                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                          - creditcard: a credit card number defined
-                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                          with any non digit characters mixed in -
-                                          ssn: a U.S. social security number following
-                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
-                                          - hexcolor: an hexadecimal color code like
-                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                          - rgbcolor: an RGB color code like rgb like
-                                          \"rgb(255,255,2559\" - byte: base64 encoded
-                                          binary data - password: any kind of string
-                                          - date: a date string like \"2006-01-02\"
-                                          as defined by full-date in RFC3339 - duration:
-                                          a duration string like \"22 ns\" as parsed
-                                          by Golang time.ParseDuration or compatible
-                                          with Scala duration format - datetime: a
-                                          date time string like \"2014-12-15T19:30:20.000Z\"
-                                          as defined by date-time in RFC3339."
-                                        type: string
-                                      id:
-                                        type: string
-                                      maxItems:
-                                        format: int64
-                                        type: integer
-                                      maxLength:
-                                        format: int64
-                                        type: integer
-                                      maxProperties:
-                                        format: int64
-                                        type: integer
-                                      maximum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      minItems:
-                                        format: int64
-                                        type: integer
-                                      minLength:
-                                        format: int64
-                                        type: integer
-                                      minProperties:
-                                        format: int64
-                                        type: integer
-                                      minimum:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      multipleOf:
-                                        description: A Number represents a JSON number
-                                          literal.
-                                        type: string
-                                      nullable:
-                                        type: boolean
-                                      pattern:
-                                        type: string
-                                      title:
-                                        type: string
-                                      type:
-                                        type: string
-                                      uniqueItems:
-                                        type: boolean
-                                      x-descriptors:
-                                        description: The list of descriptors that
-                                          determine which UI components to use on
-                                          different views
-                                        items:
-                                          type: string
-                                        type: array
-                                    type: object
-                                  type: object
-                                required:
-                                  items:
-                                    type: string
-                                  type: array
-                                title:
-                                  type: string
-                                type:
-                                  type: string
-                              type: object
-                          type: object
-                        description: Types defines the schema of the data produced/consumed
-                          by the endpoint
-                        type: object
-                      uri:
-                        description: URI can alternatively be used to specify the
-                          (Camel) endpoint explicitly
-                        type: string
-                    type: object
-                  type:
-                    type: string
                 type: object
+                x-kubernetes-preserve-unknown-fields: true
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
@@ -316,8 +93,10 @@ spec:
                     description: ErrorHandlerSpec respresents an integration error
                       handler to be used as default at runtime
                     properties:
-                      configuration:
-                        description: ErrorHandlerConfiguration --
+                      parameters:
+                        description: ErrorHandlerParameters is an unstructured object
+                          representing the configuration parameters available for
+                          an error handler
                         type: object
                         x-kubernetes-preserve-unknown-fields: true
                       type:
diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go
index e1b27e1..71774fc 100644
--- a/pkg/apis/camel/v1/common_types.go
+++ b/pkg/apis/camel/v1/common_types.go
@@ -164,13 +164,13 @@ type Flow struct {
 
 // 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"`
-	Configuration *ErrorHandlerConfiguration `json:"configuration,omitempty"`
+	Type       string                  `json:"type,omitempty"`
+	URI        string                  `json:"uri,omitempty"`
+	Parameters *ErrorHandlerParameters `json:"parameters,omitempty"`
 }
 
-// ErrorHandlerConfiguration --
-type ErrorHandlerConfiguration struct {
+// ErrorHandlerParameters is an unstructured object representing the configuration parameters available for an error handler
+type ErrorHandlerParameters struct {
 	RawMessage `json:",inline"`
 }
 
diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
new file mode 100644
index 0000000..a6b15b1
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -0,0 +1,111 @@
+/*
+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 v1alpha1
+
+import (
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+)
+
+// ErrorHandler represent an unstructured object for an error handler
+type ErrorHandler struct {
+	v1.RawMessage `json:",omitempty"`
+}
+
+// AbstractErrorHandler is a generic interface that represent any type of error handler specification
+type AbstractErrorHandler interface {
+	Type() ErrorHandlerType
+	Params() *ErrorHandlerProperties
+	Endpoint() *Endpoint
+}
+
+// ErrorHandlerNone --
+type ErrorHandlerNone struct {
+}
+
+// NewErrorHandlerNone represents a no (ignore) error handler type
+func NewErrorHandlerNone() ErrorHandlerNone {
+	return ErrorHandlerNone{}
+}
+
+// Type --
+func (e ErrorHandlerNone) Type() ErrorHandlerType {
+	return ErrorHandlerTypeNone
+}
+
+// Params --
+func (e ErrorHandlerNone) Params() *ErrorHandlerProperties {
+	return nil
+}
+
+// Endpoint --
+func (e ErrorHandlerNone) Endpoint() *Endpoint {
+	return nil
+}
+
+// ErrorHandlerLog represent a default (log) error handler type
+type ErrorHandlerLog struct {
+	Parameters *ErrorHandlerProperties `json:"parameters,omitempty"`
+}
+
+// Type --
+func (e ErrorHandlerLog) Type() ErrorHandlerType {
+	return ErrorHandlerTypeLog
+}
+
+// Params --
+func (e ErrorHandlerLog) Params() *ErrorHandlerProperties {
+	return e.Parameters
+}
+
+// Endpoint --
+func (e ErrorHandlerLog) Endpoint() *Endpoint {
+	return nil
+}
+
+// ErrorHandlerDeadLetterChannel represents a dead letter channel error handler type
+type ErrorHandlerDeadLetterChannel struct {
+	*ErrorHandlerLog
+	DLCEndpoint *Endpoint `json:"endpoint,omitempty"`
+}
+
+// Type --
+func (e ErrorHandlerDeadLetterChannel) Type() ErrorHandlerType {
+	return ErrorHandlerTypeDeadLetterChannel
+}
+
+// Params --
+func (e ErrorHandlerDeadLetterChannel) Params() *ErrorHandlerProperties {
+	return e.Parameters
+}
+
+// Endpoint --
+func (e ErrorHandlerDeadLetterChannel) Endpoint() *Endpoint {
+	return e.DLCEndpoint
+}
+
+// ErrorHandlerType --
+type ErrorHandlerType string
+
+const (
+	// ErrorHandlerTypeNone --
+	ErrorHandlerTypeNone ErrorHandlerType = "none"
+	// ErrorHandlerTypeLog --
+	ErrorHandlerTypeLog ErrorHandlerType = "log"
+	// ErrorHandlerTypeDeadLetterChannel --
+	ErrorHandlerTypeDeadLetterChannel ErrorHandlerType = "dead-letter-channel"
+)
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 367692c..5a279e1 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -38,20 +38,6 @@ type KameletBindingSpec struct {
 	Steps []Endpoint `json:"steps,omitempty"`
 }
 
-type ErrorHandler struct {
-	Endpoint      Endpoint                `json:"endpoint,omitempty"`
-	Type          ErrorHandlerType        `json:"type,omitempty"`
-	Configuration *ErrorHandlerProperties `json:"configuration,omitempty"`
-}
-
-type ErrorHandlerType string
-
-const (
-	ErrorHandlerTypeNone              ErrorHandlerType = "no"
-	ErrorHandlerTypeDefault           ErrorHandlerType = "default"
-	ErrorHandlerTypeDeadLetterChannel ErrorHandlerType = "dead-letter-channel"
-)
-
 // Endpoint represents a source/sink external entity
 type Endpoint struct {
 	// Ref can be used to declare a Kubernetes resource as source/sink endpoint
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index c4d4641..d434000 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -79,22 +79,10 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
-	var errorHandler *bindings.Binding
-	if kameletbinding.Spec.ErrorHandler.Type != "" {
-		errorHandlerURI := ""
-		if kameletbinding.Spec.ErrorHandler.Endpoint.Ref != nil || kameletbinding.Spec.ErrorHandler.Endpoint.URI != nil {
-			errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler.Endpoint)
-			if err != nil {
-				return nil, errors.Wrap(err, "could not determine error handler URI")
-			}
-
-			errorHandlerURI = errorHandler.URI
-		}
-
-		err = setIntegrationErrorHandler(&it.Spec, errorHandlerURI, kameletbinding.Spec.ErrorHandler)
-		if err != nil {
-			return nil, errors.Wrap(err, "could not set integration error handler")
-		}
+	// error handler is optional
+	errorHandler, err := maybeErrorHandler(kameletbinding.Spec.ErrorHandler, bindingContext, &it.Spec)
+	if err != nil {
+		return nil, errors.Wrap(err, "could not determine error handler")
 	}
 
 	steps := make([]*bindings.Binding, 0, len(kameletbinding.Spec.Steps))
@@ -164,19 +152,6 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	return &it, nil
 }
 
-func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandlerURI string, errorHandlerSpec v1alpha1.ErrorHandler) error {
-	it.ErrorHandler = v1.ErrorHandlerSpec{
-		Type:          string(errorHandlerSpec.Type),
-		Configuration: &v1.ErrorHandlerConfiguration{errorHandlerSpec.Configuration.RawMessage},
-	}
-
-	if errorHandlerURI != "" {
-		it.ErrorHandler.URI = errorHandlerURI
-	}
-
-	return nil
-}
-
 func determineProfile(ctx context.Context, c client.Client, binding *v1alpha1.KameletBinding) (v1.TraitProfile, error) {
 	if binding.Spec.Integration != nil && binding.Spec.Integration.Profile != "" {
 		return binding.Spec.Integration.Profile, nil
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
new file mode 100644
index 0000000..90ba3cc
--- /dev/null
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -0,0 +1,102 @@
+/*
+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 kameletbinding
+
+import (
+	"encoding/json"
+
+	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/bindings"
+	"github.com/pkg/errors"
+)
+
+func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandler, bindingContext bindings.BindingContext, itSpec *v1.IntegrationSpec) (*bindings.Binding, error) {
+	var errorHandler *bindings.Binding
+	if errHandlConf.RawMessage != nil {
+		errorHandlerSpec, err := parseErrorHandler(errHandlConf.RawMessage)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not parse error handler")
+		}
+		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
+		}
+
+		err = setIntegrationErrorHandler(itSpec, errorHandlerURI, errorHandlerSpec)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not set integration error handler")
+		}
+
+		return errorHandler, nil
+	}
+	return nil, nil
+}
+
+func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler, error) {
+	var properties map[v1alpha1.ErrorHandlerType]v1.RawMessage
+	err := json.Unmarshal(rawMessage, &properties)
+	if err != nil {
+		return nil, err
+	}
+	if len(properties) > 1 {
+		return nil, errors.Errorf("You must provide just 1 error handler, provided %d", len(properties))
+	}
+
+	for errHandlType, errHandlValue := range properties {
+		var dst v1alpha1.AbstractErrorHandler
+		switch errHandlType {
+		case v1alpha1.ErrorHandlerTypeNone:
+			dst = new(v1alpha1.ErrorHandlerNone)
+		case v1alpha1.ErrorHandlerTypeLog:
+			dst = new(v1alpha1.ErrorHandlerLog)
+		case v1alpha1.ErrorHandlerTypeDeadLetterChannel:
+			dst = new(v1alpha1.ErrorHandlerDeadLetterChannel)
+		default:
+			return nil, errors.Errorf("Unknown error type %s, supported error types are: none, log, dead-letter-channel", errHandlType)
+		}
+
+		err := json.Unmarshal(errHandlValue, dst)
+		if err != nil {
+			return nil, err
+		}
+
+		return dst, nil
+	}
+
+	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.AbstractErrorHandler) error {
+	it.ErrorHandler = v1.ErrorHandlerSpec{
+		Type: string(errorHandlerSpec.Type()),
+	}
+	if errorHandlerSpec.Params() != nil {
+		it.ErrorHandler.Parameters = &v1.ErrorHandlerParameters{errorHandlerSpec.Params().RawMessage}
+	}
+	if errorHandlerURI != "" {
+		it.ErrorHandler.URI = errorHandlerURI
+	}
+
+	return nil
+}
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index eadaa70..e82dcf9 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -107,17 +107,17 @@ func addErrorHandlerAsSource(e *Environment) error {
 
 func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
 	switch errorHandlerSpec.Type {
-	case "no":
+	case "none":
 		return `errorHandler(noErrorHandler());`, nil
-	case "default":
-		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Configuration)
+	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.Configuration)
+		errorHandlerConfiguration, err := parseErrorHandlerConfiguration(errorHandlerSpec.Parameters)
 		if err != nil {
 			return "", err
 		}
@@ -128,7 +128,7 @@ func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
 	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errorHandlerSpec.Type)
 }
 
-func parseErrorHandlerConfiguration(conf *v1.ErrorHandlerConfiguration) (string, error) {
+func parseErrorHandlerConfiguration(conf *v1.ErrorHandlerParameters) (string, error) {
 	javaPropertiesBuilder := ""
 	var properties map[string]interface{}
 	err := json.Unmarshal(conf.RawMessage, &properties)

[camel-k] 18/30: feat(trait): error handler bean

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 77282611649987f18ddf4249521efb2c211093dc
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Apr 23 15:01:46 2021 +0200

    feat(trait): error handler bean
    
    Adding capability to support a bean as expected by Camel Main  - https://camel.apache.org/components/3.7.x/others/main.html#_specifying_custom_beans
---
 pkg/apis/camel/v1alpha1/error_handler_types.go     | 113 +++++++++++----------
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |   2 +-
 pkg/controller/kameletbinding/error_handler.go     |  16 +--
 .../kameletbinding/error_handler_test.go           |  16 +++
 pkg/resources/resources.go                         |  44 ++++----
 pkg/trait/error_handler.go                         |  29 +++---
 6 files changed, 126 insertions(+), 94 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index 949fbd6..1969e2b 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -21,56 +21,72 @@ import (
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-// ErrorHandler represents an unstructured object for an error handler
-type ErrorHandler struct {
+// ErrorHandlerSpec represents an unstructured object for an error handler
+type ErrorHandlerSpec struct {
 	v1.RawMessage `json:",omitempty"`
 }
 
-// ErrorHandlerProperties represent an unstructured object for error handler parameters
-type ErrorHandlerProperties struct {
+// ErrorHandlerParameters represent an unstructured object for error handler parameters
+type ErrorHandlerParameters struct {
 	v1.RawMessage `json:",inline"`
 }
 
-// AbstractErrorHandler is a generic interface that represent any type of error handler specification
-type AbstractErrorHandler interface {
+// BeanProperties represent an unstructured object properties to be set on a bean
+type BeanProperties struct {
+	v1.RawMessage `json:",inline"`
+}
+
+// ErrorHandler is a generic interface that represent any type of error handler specification
+type ErrorHandler interface {
 	Type() ErrorHandlerType
-	Params() *ErrorHandlerProperties
+	Params() *ErrorHandlerParameters
 	Endpoint() *Endpoint
 	Ref() *string
+	Bean() *string
 }
 
-// ErrorHandlerNone --
-type ErrorHandlerNone struct {
-}
-
-// NewErrorHandlerNone represents a no (ignore) error handler type
-func NewErrorHandlerNone() ErrorHandlerNone {
-	return ErrorHandlerNone{}
+type abstractErrorHandler struct {
 }
 
 // Type --
-func (e ErrorHandlerNone) Type() ErrorHandlerType {
-	return ErrorHandlerTypeNone
+func (e abstractErrorHandler) Type() ErrorHandlerType {
+	return errorHandlerTypeAbstract
 }
 
 // Params --
-func (e ErrorHandlerNone) Params() *ErrorHandlerProperties {
+func (e abstractErrorHandler) Params() *ErrorHandlerParameters {
 	return nil
 }
 
 // Endpoint --
-func (e ErrorHandlerNone) Endpoint() *Endpoint {
+func (e abstractErrorHandler) Endpoint() *Endpoint {
 	return nil
 }
 
 // Ref --
-func (e ErrorHandlerNone) Ref() *string {
+func (e abstractErrorHandler) Ref() *string {
 	return nil
 }
 
+// Ref --
+func (e abstractErrorHandler) Bean() *string {
+	return nil
+}
+
+// ErrorHandlerNone --
+type ErrorHandlerNone struct {
+	*abstractErrorHandler
+}
+
+// Type --
+func (e ErrorHandlerNone) Type() ErrorHandlerType {
+	return ErrorHandlerTypeNone
+}
+
 // ErrorHandlerLog represent a default (log) error handler type
 type ErrorHandlerLog struct {
-	Parameters *ErrorHandlerProperties `json:"parameters,omitempty"`
+	*abstractErrorHandler
+	Parameters *ErrorHandlerParameters `json:"parameters,omitempty"`
 }
 
 // Type --
@@ -79,20 +95,10 @@ func (e ErrorHandlerLog) Type() ErrorHandlerType {
 }
 
 // Params --
-func (e ErrorHandlerLog) Params() *ErrorHandlerProperties {
+func (e ErrorHandlerLog) Params() *ErrorHandlerParameters {
 	return e.Parameters
 }
 
-// Endpoint --
-func (e ErrorHandlerLog) Endpoint() *Endpoint {
-	return nil
-}
-
-// Ref --
-func (e ErrorHandlerLog) Ref() *string {
-	return nil
-}
-
 // ErrorHandlerDeadLetterChannel represents a dead letter channel error handler type
 type ErrorHandlerDeadLetterChannel struct {
 	*ErrorHandlerLog
@@ -104,49 +110,50 @@ func (e ErrorHandlerDeadLetterChannel) Type() ErrorHandlerType {
 	return ErrorHandlerTypeDeadLetterChannel
 }
 
-// Params --
-func (e ErrorHandlerDeadLetterChannel) Params() *ErrorHandlerProperties {
-	return e.Parameters
-}
-
 // Endpoint --
 func (e ErrorHandlerDeadLetterChannel) Endpoint() *Endpoint {
 	return e.DLCEndpoint
 }
 
-// Ref --
-func (e ErrorHandlerDeadLetterChannel) Ref() *string {
-	return nil
-}
-
 // ErrorHandlerRef represents a reference to an error handler builder available in the registry
-type ErrorHandlerRef string
+type ErrorHandlerRef struct {
+	*abstractErrorHandler
+	string
+}
 
 // Type --
 func (e ErrorHandlerRef) Type() ErrorHandlerType {
 	return ErrorHandlerTypeRef
 }
 
-// Params --
-func (e ErrorHandlerRef) Params() *ErrorHandlerProperties {
-	return nil
+// Ref --
+func (e ErrorHandlerRef) Ref() *string {
+	s := string(e.string)
+	return &s
 }
 
-// Endpoint --
-func (e ErrorHandlerRef) Endpoint() *Endpoint {
-	return nil
+// ErrorHandlerBean represents a bean error handler type
+type ErrorHandlerBean struct {
+	*ErrorHandlerLog
+	BeanType   *string         `json:"type,omitempty"`
+	Properties *BeanProperties `json:"properties,omitempty"`
 }
 
-// Ref --
-func (e ErrorHandlerRef) Ref() *string {
-	s := string(e)
-	return &s
+// Type --
+func (e ErrorHandlerBean) Type() ErrorHandlerType {
+	return ErrorHandlerTypeBean
+}
+
+// Bean --
+func (e ErrorHandlerBean) Bean() *string {
+	return e.BeanType
 }
 
 // ErrorHandlerType --
 type ErrorHandlerType string
 
 const (
+	errorHandlerTypeAbstract ErrorHandlerType = ""
 	// ErrorHandlerTypeNone --
 	ErrorHandlerTypeNone ErrorHandlerType = "none"
 	// ErrorHandlerTypeLog --
@@ -155,4 +162,6 @@ const (
 	ErrorHandlerTypeDeadLetterChannel ErrorHandlerType = "dead-letter-channel"
 	// ErrorHandlerTypeRef --
 	ErrorHandlerTypeRef ErrorHandlerType = "ref"
+	// ErrorHandlerTypeBean --
+	ErrorHandlerTypeBean ErrorHandlerType = "bean"
 )
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 62e8079..cfe8779 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -33,7 +33,7 @@ type KameletBindingSpec struct {
 	// Sink is the destination of the integration defined by this binding
 	Sink Endpoint `json:"sink,omitempty"`
 	// ErrorHandler is an optional handler called upon an error occuring in the integration
-	ErrorHandler ErrorHandler `json:"errorHandler,omitempty"`
+	ErrorHandler ErrorHandlerSpec `json:"errorHandler,omitempty"`
 	// Steps contains an optional list of intermediate steps that are executed between the Source and the Sink
 	Steps []Endpoint `json:"steps,omitempty"`
 }
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index c9858f9..15e72bb 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -26,7 +26,7 @@ import (
 	"github.com/pkg/errors"
 )
 
-func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandler, bindingContext bindings.BindingContext, itSpec *v1.IntegrationSpec) (*bindings.Binding, error) {
+func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandlerSpec, bindingContext bindings.BindingContext, itSpec *v1.IntegrationSpec) (*bindings.Binding, error) {
 	var errorHandler *bindings.Binding
 	if errHandlConf.RawMessage != nil {
 		errorHandlerSpec, err := parseErrorHandler(errHandlConf.RawMessage)
@@ -41,10 +41,10 @@ func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandler, bindingContext bindin
 			}
 
 			errorHandlerURI = errorHandler.URI
-		}
-
-		if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeRef {
+		} else if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeRef {
 			errorHandlerURI = *errorHandlerSpec.Ref()
+		} else if errorHandlerSpec.Type() == v1alpha1.ErrorHandlerTypeBean {
+			errorHandlerURI = *errorHandlerSpec.Bean()
 		}
 
 		err = setIntegrationErrorHandler(itSpec, errorHandlerURI, errorHandlerSpec)
@@ -57,7 +57,7 @@ func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandler, bindingContext bindin
 	return nil, nil
 }
 
-func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler, error) {
+func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.ErrorHandler, error) {
 	var properties map[v1alpha1.ErrorHandlerType]v1.RawMessage
 	err := json.Unmarshal(rawMessage, &properties)
 	if err != nil {
@@ -68,7 +68,7 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler,
 	}
 
 	for errHandlType, errHandlValue := range properties {
-		var dst v1alpha1.AbstractErrorHandler
+		var dst v1alpha1.ErrorHandler
 		switch errHandlType {
 		case v1alpha1.ErrorHandlerTypeNone:
 			dst = new(v1alpha1.ErrorHandlerNone)
@@ -78,6 +78,8 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler,
 			dst = new(v1alpha1.ErrorHandlerDeadLetterChannel)
 		case v1alpha1.ErrorHandlerTypeRef:
 			dst = new(v1alpha1.ErrorHandlerRef)
+		case v1alpha1.ErrorHandlerTypeBean:
+			dst = new(v1alpha1.ErrorHandlerBean)
 		default:
 			return nil, errors.Errorf("Unknown error type %s, supported error types are: none, log, dead-letter-channel", errHandlType)
 		}
@@ -93,7 +95,7 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.AbstractErrorHandler,
 	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.AbstractErrorHandler) error {
+func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandlerURI string, errorHandlerSpec v1alpha1.ErrorHandler) error {
 	it.ErrorHandler = v1.ErrorHandlerSpec{
 		Type: string(errorHandlerSpec.Type()),
 	}
diff --git a/pkg/controller/kameletbinding/error_handler_test.go b/pkg/controller/kameletbinding/error_handler_test.go
index 1600707..40864b9 100644
--- a/pkg/controller/kameletbinding/error_handler_test.go
+++ b/pkg/controller/kameletbinding/error_handler_test.go
@@ -75,3 +75,19 @@ func TestParseErrorHandlerDLCWithParametersDoesSucceed(t *testing.T) {
 	assert.Equal(t, "someUri", *dlcErrorHandler.Endpoint().URI)
 	assert.NotNil(t, dlcErrorHandler.Params())
 }
+
+func TestParseErrorHandlerBeanWithParametersDoesSucceed(t *testing.T) {
+	beanErrorHandler, err := parseErrorHandler(
+		[]byte(`{
+			"bean": {
+				"type": "com.acme.MyType", 
+				"parameters": 
+					[{"param1": "value1"}]
+			}
+		}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeBean, beanErrorHandler.Type())
+	assert.Equal(t, "com.acme.MyType", *beanErrorHandler.Bean())
+	assert.NotNil(t, beanErrorHandler.Params())
+}
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 6b712ac..5c771bb 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -106,16 +106,16 @@ var assets = func() http.FileSystem {
 		"/crd/bases/camel.apache.org_integrations.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_integrations.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 23405,
+			uncompressedSize: 24066,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\x5d\x73\xdb\xba\x95\xef\xfa\x15\x67\xec\x87\xdc\xcc\x48\x54\x93\xb4\xb3\x3b\xde\x27\xd7\x89\x77\xb5\xf1\xb5\x33\x96\xd3\x3b\x77\x3a\x7d\x80\xc8\x43\x0a\x35\x08\x70\x01\xd0\xb2\xda\xe9\x7f\xdf\x39\x07\x24\x45\x4a\xa4\xac\xc8\xb9\xf7\x76\xbb\xe2\x4b\x62\x12\x38\x38\xdf\x5f\x00\x74\x0e\x93\xef\xf7\x8c\xce\xe1\x46\xc6\xa8\x1d\x26\xe0\x0d\xf8\x25\xc2\x65\x21\xe2\x25\xc2\xdc\xa4\x7e\x25\x2c\xc2\xb5\x29\x75\x22\xbc\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\x5d\x73\xe3\xb8\x91\xef\xfa\x15\x5d\xf6\xc3\xec\x56\x49\x54\x66\x26\xa9\xbb\xf2\x3d\x79\x3d\x33\x17\xdd\x78\x6d\x97\xe5\xc9\xd6\x56\x2a\x0f\x10\xd9\x12\x11\x83\x00\x0f\x00\x25\x2b\xa9\xfc\xf7\xab\x6e\x90\x14\x29\x91\xb4\xc6\x9e\xdd\xcd\x25\xe2\xcb\x8c\x49\xa0\xd1\xdf\x5f\x00\x74\x0e\x93\x6f\xf7\x8c\xce\xe1\x5a\xc6\xa8\x1d\x26\xe0\x0d\xf8\x14\xe1\x32\x17\x71\x8a\x30\x37\x4b\xbf\x11\x16\xe1\x93\x29\x74\x22\xbc\x [...]
 		},
 		"/crd/bases/camel.apache.org_kameletbindings.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kameletbindings.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 55181,
+			uncompressedSize: 56150,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x01\x4b\x8e\xe3\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\x7b\x7e\xed\xa6\x45\x92\xde\xe1\x5e\xdb\x03\x68\x69\x6c\xf3\x22\x91\x3a\x92\x8a\xe3\xef\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x99\x72\xec\x6e\x0a\x88\xc0\x62\x6b\x8b\x1a\xce\x0c\x87\xc3\x99\x21\x3f\xce\x11\x78\xbb\x6b\x07\x47\xf0\x9e\x06\xc8\x24\x86\xa0\x38\xa8\x29\xc2\x59\x42\x82\x29\xc2\x35\x1f\xab\x19\x11\x08\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x81\x48\x8e\x93\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\xfb\xfa\xb5\x9b\x06\x49\x7a\x87\x7b\x6d\x0f\xa0\xa5\xb1\xcd\x8b\x44\xea\x48\x2a\x8e\xdf\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x89\x72\xec\x6e\x0b\x88\x40\xd1\xd8\xa6\x86\x33\xc3\x99\xe1\x70\xc8\x8f\x7d\x00\xde\xf6\xda\xde\x01\xbc\xa7\x01\x32\x89\x21\x28\x0e\x6a\x8a\x70\x96\x90\x60\x8a\x70\xc3\xc7\x6a\x46\x04\xc2\x [...]
 		},
 		"/crd/bases/camel.apache.org_kamelets.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kamelets.yaml",
@@ -238,13 +238,6 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x6f\xab\x46\x14\xdd\xcf\xaf\x38\x32\x9b\xf7\x24\x1b\xb7\x5d\x55\xee\x8a\x97\xd8\x2d\x6a\x64\x4b\xc6\x69\x94\xe5\x78\xb8\xc0\xad\x61\x2e\x9d\x19\x42\xdc\x5f\x5f\x0d\xb6\x9b\x44\x55\xab\x2e\x32\x2b\x10\x97\xf3\x71\xcf\x99\x04\x8b\xcf\x3b\x2a\xc1\x03\x1b\xb2\x9e\x4a\x04\x41\x68\x08\x59\xaf\x4d\x43\x28\xa4\x0a\xa3\x76\x84\x8d\x0c\xb6\xd4\x81\xc5\xe2\x4b\x56\x6c\xbe\x62\xb0\x25\x39\x88\x25\x88\x43\x27\x8e\x54\x [...]
 		},
-		"/rbac/operator-role-binding-podmonitors.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "operator-role-binding-podmonitors.yaml",
-			modTime:          time.Time{},
-			uncompressedSize: 1229,
-
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x72\x36\xbb\xad\xd0\xc0\x06\x2c\xa7\x41\x8e\x34\x35\x96\xa6\x2b\x71\xd8\x21\xb5\x8a\xfb\xeb\x0b\xca\x76\x77\x83\xa2\x45\x0f\xe1\x4d\xd0\xf0\x7d\xcc\x7b\x2c\xb0\xfc\x76\xc7\x14\xf8\xc0\x8e\x7c\xa4\x06\x49\x90\x3a\xc2\x26\x58\xd7\x11\x6a\x39\xa5\xc9\x2a\xe1\x51\x46\xdf\xd8\xc4\xe2\xf1\x66\x53\x3f\xbe\xc5\xe8\x1b\x52\x88\x27\x88\x62\x10\x25\x [...]
-		},
 		"/rbac/operator-role-binding-service-binding.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-binding-service-binding.yaml",
 			modTime:          time.Time{},
@@ -252,6 +245,13 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xcf\x6f\xf2\x46\x10\xbd\xef\x5f\xf1\x84\x2f\xdf\x27\x81\x69\x7b\xaa\xe8\xc9\x5f\x02\xad\xd5\x08\x24\x4c\x1a\xe5\xb8\x5e\x0f\xf6\x14\x7b\xc7\xdd\x5d\xc7\xa1\x7f\x7d\xb5\x06\x9a\x44\x55\x2b\x55\xca\xde\x10\x33\xef\xc7\xbc\xe7\x04\x8b\xcf\x7b\x2a\xc1\x03\x1b\xb2\x9e\x2a\x04\x41\x68\x08\x59\xaf\x4d\x43\x28\xe4\x18\x46\xed\x08\x1b\x19\x6c\xa5\x03\x8b\xc5\x97\xac\xd8\x7c\xc5\x60\x2b\x72\x10\x4b\x10\x87\x4e\x1c\xa9\x [...]
 		},
+		"/rbac/operator-role-binding-servicemonitors.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "operator-role-binding-servicemonitors.yaml",
+			modTime:          time.Time{},
+			uncompressedSize: 1237,
+
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x52\x36\xeb\x56\x68\x60\x03\x96\xd3\x20\x47\x9a\x1a\x4b\x53\x4b\x1c\x75\x48\xad\xe2\xfe\xfa\x82\xb2\xdd\xdd\xa0\x68\x81\x02\xe1\xcd\xf0\xcc\xfb\x98\xf7\x94\x61\xf9\xed\x9e\xc9\xf0\x81\x1d\xf9\x40\x35\xa2\x20\xb6\x84\x62\xb0\xae\x25\x54\x72\x8a\x93\x55\xc2\x46\x46\x5f\xdb\xc8\xe2\xf1\xa6\xa8\x36\x6f\x31\xfa\x9a\x14\xe2\x09\xa2\xe8\x45\xc9\x [...]
+		},
 		"/rbac/operator-role-binding-strimzi.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-binding-strimzi.yaml",
 			modTime:          time.Time{},
@@ -301,13 +301,6 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x53\xc1\x8e\xdb\x46\x0c\xbd\xeb\x2b\x1e\xac\x4b\x02\xac\xe5\xb6\xa7\xc2\x3d\xb9\xc9\x6e\x6b\x34\xb0\x81\x95\xd3\x20\x47\x7a\x44\x4b\xc4\x8e\x86\xea\xcc\x68\x95\xed\xd7\x17\x33\xb6\x13\x6f\xdd\x6d\x2e\x01\xa2\x8b\x68\xf2\x89\x7c\x8f\x8f\x2e\x31\xff\x76\x4f\x51\xe2\x9d\x18\x76\x81\x1b\x44\x45\xec\x18\xab\x81\x4c\xc7\xa8\xf5\x10\x27\xf2\x8c\x3b\x1d\x5d\x43\x51\xd4\xe1\xd5\xaa\xbe\x7b\x8d\xd1\x35\xec\xa1\x8e\xa1\x1e\x [...]
 		},
-		"/rbac/operator-role-podmonitors.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "operator-role-podmonitors.yaml",
-			modTime:          time.Time{},
-			uncompressedSize: 1242,
-
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x72\x37\xbb\xad\xd0\xc0\x06\x56\x4e\x83\x1c\x69\x6a\x2c\x0d\x96\xe2\xb0\x43\x6a\x95\xed\xaf\x2f\x24\xcb\xcd\x1a\xb9\x86\x17\x8f\xc9\xe1\xfb\xe0\x1b\x15\x58\xff\xb8\x65\x0a\x7c\x64\x47\x21\x51\x83\x2c\xc8\x1d\x61\x17\xad\xeb\x08\xb5\x9c\xf3\x68\x95\xf0\x28\x43\x68\x6c\x66\x09\x78\xb7\xab\x1f\xdf\x63\x08\x0d\x29\x24\x10\x44\xd1\x8b\x92\x29\x [...]
-		},
 		"/rbac/operator-role-service-binding.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-service-binding.yaml",
 			modTime:          time.Time{},
@@ -315,6 +308,13 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xc1\x6e\xdc\x36\x10\xbd\xf3\x2b\x1e\x56\x97\x04\xb0\xe4\xb6\xa7\x62\x7b\xda\x3a\x76\x2b\x34\xd8\x05\xac\x4d\x83\x1c\xb9\xd4\xac\x34\x30\xc5\x51\x87\x94\x15\xf7\xeb\x0b\x6a\xb5\x89\x8d\x5e\xa3\x0b\x47\xe4\xcc\x9b\xf7\xf8\x86\x05\xca\x1f\xf7\x99\x02\x1f\xd9\x51\x88\xd4\x22\x09\x52\x4f\xd8\x8d\xd6\xf5\x84\x46\xce\x69\xb6\x4a\x78\x90\x29\xb4\x36\xb1\x04\xbc\xdb\x35\x0f\xef\x31\x85\x96\x14\x12\x08\xa2\x18\x44\xc9\x [...]
 		},
+		"/rbac/operator-role-servicemonitors.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "operator-role-servicemonitors.yaml",
+			modTime:          time.Time{},
+			uncompressedSize: 1250,
+
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xc1\x8e\xdb\x36\x10\xbd\xf3\x2b\x1e\xac\x4b\x02\xac\xe5\xb6\xa7\xc2\x3d\xb9\x9b\xdd\x56\x68\x60\x03\x2b\xa7\x41\x8e\x34\x35\x96\x06\x4b\x71\xd4\x21\xb5\x8a\xfb\xf5\x85\x68\xb9\xd9\x45\xae\xe1\xc5\x63\x72\x66\xde\x7b\xf3\x46\x05\xd6\x3f\xee\x98\x02\x1f\xd9\x51\x88\xd4\x20\x09\x52\x47\xd8\x0d\xd6\x75\x84\x5a\xce\x69\xb2\x4a\x78\x94\x31\x34\x36\xb1\x04\xbc\xdb\xd5\x8f\xef\x31\x86\x86\x14\x12\x08\xa2\xe8\x45\xc9\x [...]
+		},
 		"/rbac/operator-role-strimzi.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-strimzi.yaml",
 			modTime:          time.Time{},
@@ -467,9 +467,9 @@ var assets = func() http.FileSystem {
 		"/traits.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "traits.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 36744,
+			uncompressedSize: 37171,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1c\xb7\xd1\xe0\x77\xfd\x0a\x14\x9f\xab\xe2\x4b\xed\x0e\x29\xa7\x9c\xf8\xf6\x4e\x97\xa2\x25\x25\xa1\x6d\x49\x3c\x51\x71\xea\x4a\xa7\xca\x62\x67\x7a\x77\x21\x62\x80\x09\x80\x59\x6a\x73\x75\xff\xfd\x0a\xdd\x00\x06\x33\x3b\x24\x97\xb2\xe9\x32\xaf\x9e\xe4\x83\x45\x72\xa6\xd1\x68\x34\xfa\xbd\x7b\x9c\xe1\xc2\xd9\xd9\xb3\x29\x53\xbc\x86\x19\xe3\xcb\xa5\x50\xc2\x6d\x9f\x31\xd6\x48\xee\x96\xda\xd4\x33\xb6\xe4\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xed\x72\x1c\xb7\x11\xe0\x7f\x3d\x05\x8a\xb9\x2a\x7e\xd4\xee\x90\x72\xca\xb1\xb3\x77\xba\x14\x2d\x29\x09\x6d\x4b\xe2\x89\x8a\x53\x57\x3a\x57\x16\x3b\xd3\xbb\x0b\x11\x03\x4c\x00\x0c\xa9\xcd\xd5\xbd\xfb\x15\xba\x01\x0c\x66\x77\xb8\x1c\xca\xa6\xcb\xbc\xba\xe4\x87\x45\x72\xa6\xd1\x68\x34\xfa\xbb\x7b\x9c\xe1\xc2\xd9\xd9\xb3\x29\x53\xbc\x86\x19\xe3\xcb\xa5\x50\xc2\x6d\x9e\x31\xd6\x48\xee\x96\xda\xd4\x33\xb6\xe4\xd2\x [...]
 		},
 	}
 	fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
@@ -524,8 +524,8 @@ var assets = func() http.FileSystem {
 		fs["/rbac/operator-role-binding-knative.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-leases.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-openshift.yaml"].(os.FileInfo),
-		fs["/rbac/operator-role-binding-podmonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-service-binding.yaml"].(os.FileInfo),
+		fs["/rbac/operator-role-binding-servicemonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-strimzi.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-events.yaml"].(os.FileInfo),
@@ -533,8 +533,8 @@ var assets = func() http.FileSystem {
 		fs["/rbac/operator-role-kubernetes.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-leases.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-openshift.yaml"].(os.FileInfo),
-		fs["/rbac/operator-role-podmonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-service-binding.yaml"].(os.FileInfo),
+		fs["/rbac/operator-role-servicemonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-strimzi.yaml"].(os.FileInfo),
 		fs["/rbac/user-cluster-role.yaml"].(os.FileInfo),
 		fs["/rbac/user-global-kamelet-viewer-role-binding.yaml"].(os.FileInfo),
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index 7945372..c2aee73 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -68,7 +68,7 @@ func (t *errorHandlerTrait) Apply(e *Environment) error {
 }
 
 func addErrorHandlerAsSource(e *Environment) error {
-	errorHandlerStatement, err := parseErrorHandler(e.Integration.Spec.ErrorHandler)
+	errorHandlerStatement, err := parseErrorHandler(e)
 	if err != nil {
 		return err
 	}
@@ -91,21 +91,22 @@ func addErrorHandlerAsSource(e *Environment) error {
 		Type:     v1.SourceTypeErrorHandler,
 	}
 
-	replaced := false
-	for idx, existing := range e.Integration.Status.GeneratedSources {
-		if existing.Name == errorHandlerSource.Name {
-			replaced = true
-			e.Integration.Status.GeneratedSources[idx] = errorHandlerSource
-		}
-	}
-	if !replaced {
-		e.Integration.Status.GeneratedSources = append(e.Integration.Status.GeneratedSources, errorHandlerSource)
-	}
+	e.Integration.Status.AddOrReplaceGeneratedSources(errorHandlerSource)
 
 	return nil
 }
 
-func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
+func addErrorHandlerBeanConfiguration(e *Environment, fqn string) error {
+	// camel.beans.defaultErrorHandler = #class:the-full-qualified-class-name
+	e.Integration.Status.AddConfigurationsIfMissing(v1.ConfigurationSpec{
+		Type:  "property",
+		Value: fmt.Sprintf("camel.beans.defaultErrorHandler=#class:%s", fqn),
+	})
+	return nil
+}
+
+func parseErrorHandler(e *Environment) (string, error) {
+	errorHandlerSpec := e.Integration.Spec.ErrorHandler
 	switch errorHandlerSpec.Type {
 	case "none":
 		return `errorHandler(noErrorHandler());`, nil
@@ -126,6 +127,10 @@ func parseErrorHandler(errorHandlerSpec v1.ErrorHandlerSpec) (string, error) {
 	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)

[camel-k] 06/30: doc(example): error handling kamelet binding

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 924378e018a7b458754a8f18e9a9484d39cb4007
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 13 14:22:32 2021 +0200

    doc(example): error handling kamelet binding
---
 ...ror-handler.yaml => error-handler.kamelet.yaml} | 38 ++++++++-------
 .../kamelets/error-handler/error-sink.kamelet.yaml | 44 -----------------
 ...ler.yaml => incremental-id-source.kamelet.yaml} | 47 +++++++++++-------
 .../kamelet-binding-error-handler.yaml             | 17 ++++---
 ...ng-error-handler.yaml => log-sink.kamelet.yaml} | 30 +++++-------
 examples/kamelets/error-handler/readme.md          | 57 ++++++++++++++--------
 .../error-handler/timer-source.kamelet.yaml        | 54 --------------------
 7 files changed, 107 insertions(+), 180 deletions(-)

diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/error-handler.kamelet.yaml
similarity index 56%
copy from examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
copy to examples/kamelets/error-handler/error-handler.kamelet.yaml
index d731d1f..dbfc4bb 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/error-handler.kamelet.yaml
@@ -16,23 +16,25 @@
 # ---------------------------------------------------------------------------
 
 apiVersion: camel.apache.org/v1alpha1
-kind: KameletBinding
+kind: Kamelet
 metadata:
-  name: http-error-source
+  name: error-handler
 spec:
-  source:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: timer-source
-    properties:
-      message: "Hello world!"
-  sink:
-    uri: https://log-source/failing-service
-  errorHandler:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: error-sink
-    properties:
-     defaultMessage: "ERROR ERROR!"      
+  sources:
+  - content: |
+      import org.apache.camel.builder.RouteBuilder;
+      public class ErrorHandlerSource extends RouteBuilder {
+        @Override
+        public void configure() throws Exception {
+            errorHandler(deadLetterChannel("log:error?showCaughtException=true&showException=true&showHeaders=true"));
+        }
+      }
+    name: ErrorHandlerSource.java
+  definition:
+    title: "Error Handler Log DLC"
+    description: "Dead letter channel"
+# We can use the below once this is fixed https://issues.apache.org/jira/browse/CAMEL-16486
+#  flow:
+#    error-handler:
+#      dead-letter-channel:
+#        dead-letter-uri: log:error-sink?showCaughtException=true&showException=true&showHeaders=true
diff --git a/examples/kamelets/error-handler/error-sink.kamelet.yaml b/examples/kamelets/error-handler/error-sink.kamelet.yaml
deleted file mode 100644
index e35a54d..0000000
--- a/examples/kamelets/error-handler/error-sink.kamelet.yaml
+++ /dev/null
@@ -1,44 +0,0 @@
-# ---------------------------------------------------------------------------
-# 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.
-# ---------------------------------------------------------------------------
-
-apiVersion: camel.apache.org/v1alpha1
-kind: Kamelet
-metadata:
-  name: error-sink
-  annotations:
-    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAACcBJREFUeJzt3XmsHVUdwPHva21poWGTUpAiVRQSFjWAyi5LcCmKLCEouLwQccMgGsISEkQRXMIfSKMGhQSMCCibkRIgghQEF4RIQYtG4YFsraRlb6G+1j9+94a50/fmvuW+OTN3vp9kkrnnzj3zu+/N786ZmTNnQJIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZKkfjOQOoAKGQA+DJwAvBfYCpieNKKJexk4E/h56kDUH94O3AOs76NpHfDlXv6R1Ey7ACtIv0FP1XRa7/5Uapo5wL9JvxFP9fSNXv3Bmu [...]
-  labels:
-    camel.apache.org/kamelet.type: "sink"
-spec:
-  definition:
-    title: "Error Log Sink"
-    description: "Consume events from a channel"
-    required:
-      - defaultMessage
-    properties:
-      defaultMessage:
-        title: Message
-        description: The default message to log
-        type: string
-        example: "error while checking the source"    
-  flow:
-    from:
-      uri: kamelet:source
-      steps:
-      - set-body:
-          constant: "{{defaultMessage}}"
-      - to: "log:error-sink"
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
similarity index 55%
copy from examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
copy to examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
index d731d1f..5e3181b 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/incremental-id-source.kamelet.yaml
@@ -16,23 +16,36 @@
 # ---------------------------------------------------------------------------
 
 apiVersion: camel.apache.org/v1alpha1
-kind: KameletBinding
+kind: Kamelet
 metadata:
-  name: http-error-source
+  name: incremental-id-source
+  labels:
+    camel.apache.org/kamelet.type: "source"
 spec:
-  source:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: timer-source
+  definition:
+    title: "Incremental ID Source"
+    description: "Produces periodic events with an incremental ID"
     properties:
-      message: "Hello world!"
-  sink:
-    uri: https://log-source/failing-service
-  errorHandler:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: error-sink
-    properties:
-     defaultMessage: "ERROR ERROR!"      
+      period:
+        title: Period
+        description: The interval between two events
+        type: integer
+        default: 1000
+  types:
+    out:
+      mediaType: text/plain
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "{{period}}"
+      steps:
+      - set-body:
+          simple: "Producing message #${exchangeProperty.CamelTimerCounter}"
+      - choice:
+          when:
+          - simple: "${bodyAs(String)} contains 0"
+            steps:
+            - set-body:
+                simple: "${mandatoryBodyAs(Boolean)}"
+      - to: "kamelet:sink"                
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index d731d1f..3602831 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -18,21 +18,22 @@
 apiVersion: camel.apache.org/v1alpha1
 kind: KameletBinding
 metadata:
-  name: http-error-source
+  name: kamelet-binding-error-handler
 spec:
   source:
     ref:
       kind: Kamelet
       apiVersion: camel.apache.org/v1alpha1
-      name: timer-source
-    properties:
-      message: "Hello world!"
+      name: incremental-id-source
   sink:
-    uri: https://log-source/failing-service
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: log-sink
   errorHandler:
     ref:
       kind: Kamelet
       apiVersion: camel.apache.org/v1alpha1
-      name: error-sink
-    properties:
-     defaultMessage: "ERROR ERROR!"      
+      name: error-handler    
+#    uri: kamelet:error-handler
+    
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/log-sink.kamelet.yaml
similarity index 70%
copy from examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
copy to examples/kamelets/error-handler/log-sink.kamelet.yaml
index d731d1f..aa11481 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/log-sink.kamelet.yaml
@@ -16,23 +16,17 @@
 # ---------------------------------------------------------------------------
 
 apiVersion: camel.apache.org/v1alpha1
-kind: KameletBinding
+kind: Kamelet
 metadata:
-  name: http-error-source
+  name: log-sink
+  labels:
+    camel.apache.org/kamelet.type: "sink"
 spec:
-  source:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: timer-source
-    properties:
-      message: "Hello world!"
-  sink:
-    uri: https://log-source/failing-service
-  errorHandler:
-    ref:
-      kind: Kamelet
-      apiVersion: camel.apache.org/v1alpha1
-      name: error-sink
-    properties:
-     defaultMessage: "ERROR ERROR!"      
+  definition:
+    title: "Regular Log Sink"
+    description: "Consume events from a channel"  
+  flow:
+    from:
+      uri: kamelet:source
+      steps:
+      - to: "log:ok"
diff --git a/examples/kamelets/error-handler/readme.md b/examples/kamelets/error-handler/readme.md
index 5438050..5ff4777 100644
--- a/examples/kamelets/error-handler/readme.md
+++ b/examples/kamelets/error-handler/readme.md
@@ -1,49 +1,64 @@
 # Kamelets Binding Error Handler example
-This example shows how to create a simple _timer-source_ `kamelet` bound to a failing sink in a `KameletBinding`. With the support of the `ErrorHandler` we will be able to redirect all errors to a `Dead Letter Channel` _error-sink_ `Kamelet`.
+This example shows how to create a simple _source_ `kamelet` bound to a log _sink_ in a `KameletBinding`. With the support of the `ErrorHandler` we will be able to redirect all errors to a `Dead Letter Channel` _error-handler_ `Kamelet`.
 
-## Timer Source Kamelet
-First of all, you must install the _timer-source_ Kamelet defined in `timer-source.kamelet.yaml` file:
+## Incremental ID Source Kamelet
+First of all, you must install the _incremental-id-source_ Kamelet defined in `incremental-id-source.kamelet.yaml` file. This source will emit events every second with an autoincrement counter that will be forced to fail when the number 0 is caught. With this trick, we will simulate possible event faults.
 ```
-$ kubectl apply -f timer-source.kamelet.yaml
+$ kubectl apply -f incremental-id-source.kamelet.yaml
 ```
 You can check the newly created `kamelet` checking the list of kamelets available:
 ```
 $ kubectl get kamelets
 
-NAME                   PHASE
-timer-source           Ready
+NAME                            PHASE
+incremental-id-source           Ready
 ```
-## Error Sink Kamelet
-Now it's the turn of installing the _error-sink_ Kamelet defined in `error-sink.kamelet.yaml` file:
+## Log Sink Kamelet
+Now it's the turn of installing the log-sink_ Kamelet defined in `log-sink.kamelet.yaml` file:
 ```
-$ kubectl apply -f error-sink.kamelet.yaml
+$ kubectl apply -f log-sink.kamelet.yaml
 ```
 You can check the newly created `kamelet` checking the list of kamelets available:
 ```
 $ kubectl get kamelets
 
-NAME           PHASE
-error-sink     Ready
-timer-source   Ready
+NAME                    PHASE
+log-sink                Ready
+incremental-id-source   Ready
+```
+## Error handler  Kamelet
+We finally install an error handler as a dead letter channel as specified in `error-handler.kamelet.yaml` file. You can specify any kind of error handler as expected by Apache Camel runtime.
+```
+$ kubectl apply -f error-handler.kamelet.yaml
+```
+You can check the newly created `kamelet` checking the list of kamelets available:
+```
+$ kubectl get kamelets
+
+NAME                    PHASE
+error-handler           Ready
+log-sink                Ready
+incremental-id-source   Ready
 ```
 ## Error Handler Kamelet Binding
-We can create a `KameletBinding` which is triggered by the _timer-source_ `Kamelet` and define a fake sink URI in order to make it fail on purpose. Then we can configure an _errorHandler_ as defined in `kamelet-binding-error-handler.yaml` file:
+We can create a `KameletBinding` which is triggered by the _incremental-id-source_ `Kamelet` and log events to _log-sink_ `Kamelet`. As this will sporadically fail, we can configure an _errorHandler_ as defined in `kamelet-binding-error-handler.yaml` file:
 ```
+...
   errorHandler:
     ref:
       kind: Kamelet
       apiVersion: camel.apache.org/v1alpha1
-      name: log-sink
-    properties:
-     defaultMessage: "ERROR ERROR!" 
+      name: error-handler
 ```
 Execute the following command to start the `Integration`:
 ```
 kubectl apply -f kamelet-binding-error-handler.yaml
 ```
-As soon as the `Integration` starts, it will log a message error for every failure it will print:
+As soon as the `Integration` starts, it will log the events on the `ok` log channel and errors on the `error` log channel:
+```
+[1] 2021-04-13 10:33:38,375 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #8]
+[1] 2021-04-13 10:33:39,376 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #9]
+[1] 2021-04-13 10:33:40,409 INFO  [error] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, Headers: {firedTime=Tue Apr 13 10:33:40 GMT 2021}, BodyType: String, Body: Producing message #10, CaughtExceptionType: org.apache.camel.CamelExecutionException, CaughtExceptionMessage: Exception occurred during execution on the exchange: Exchange[]]
+[1] 2021-04-13 10:33:41,375 INFO  [ok] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: Producing message #11]
 ```
-[1] 2021-03-16 15:11:33,099 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
-[1] 2021-03-16 15:11:33,988 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
-[1] 2021-03-16 15:11:34,988 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
-```
\ No newline at end of file
+This example is useful to guide you through the configuration of an error handler. In a production environment you will likely configure the error handler with a `Dead Letter Channel` pointing to a persistent queue.
\ No newline at end of file
diff --git a/examples/kamelets/error-handler/timer-source.kamelet.yaml b/examples/kamelets/error-handler/timer-source.kamelet.yaml
deleted file mode 100644
index f837fb5..0000000
--- a/examples/kamelets/error-handler/timer-source.kamelet.yaml
+++ /dev/null
@@ -1,54 +0,0 @@
-# ---------------------------------------------------------------------------
-# 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.
-# ---------------------------------------------------------------------------
-
-apiVersion: camel.apache.org/v1alpha1
-kind: Kamelet
-metadata:
-  name: timer-source
-  annotations:
-    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm [...]
-  labels:
-    camel.apache.org/kamelet.type: "source"
-spec:
-  definition:
-    title: "Timer Source"
-    description: "Produces periodic events with a custom payload"
-    required:
-      - message
-    properties:
-      period:
-        title: Period
-        description: The interval between two events
-        type: integer
-        default: 1000
-      message:
-        title: Message
-        description: The message to generate
-        type: string
-        example: "hello world"
-  types:
-    out:
-      mediaType: text/plain
-  flow:
-    from:
-      uri: timer:tick
-      parameters:
-        period: "{{period}}"
-      steps:
-      - set-body:
-          constant: "{{message}}"
-      - to: "kamelet:sink"

[camel-k] 23/30: refactor(controller): error handler useless uri

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 2f621da116d86429e3a52c8748171919b68c5819
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 10:52:21 2021 +0200

    refactor(controller): error handler useless uri
---
 pkg/controller/kameletbinding/error_handler.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index 1d71683..5325324 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -41,9 +41,8 @@ func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandlerSpec, bindingContext bi
 				return nil, errors.Wrap(err, "could not determine error handler URI")
 			}
 		} else {
-			// Create a new binding otherwise in order to store application properties
+			// Create a new binding otherwise in order to store error handler application properties
 			errorHandlerBinding = &bindings.Binding{
-				URI:                   "error-handler",
 				ApplicationProperties: make(map[string]string),
 			}
 		}

[camel-k] 25/30: chore(crd): error handler generated crds

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 88d3706f0ffcce829ebaa07082824241526238fc
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 11:28:29 2021 +0200

    chore(crd): error handler generated crds
---
 config/crd/bases/camel.apache.org_integrations.yaml       | 15 ---------------
 config/crd/bases/camel.apache.org_kameletbindings.yaml    | 15 ---------------
 .../1.5.0-snapshot/camel.apache.org_kameletbindings.yaml  |  5 +++++
 helm/camel-k/crds/crd-integration.yaml                    | 15 ---------------
 helm/camel-k/crds/crd-kamelet-binding.yaml                | 15 ---------------
 5 files changed, 5 insertions(+), 60 deletions(-)

diff --git a/config/crd/bases/camel.apache.org_integrations.yaml b/config/crd/bases/camel.apache.org_integrations.yaml
index 0b1b88a..96e26b9 100644
--- a/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/config/crd/bases/camel.apache.org_integrations.yaml
@@ -88,21 +88,6 @@ spec:
                 items:
                   type: string
                 type: array
-              errorHandler:
-                description: ErrorHandlerSpec respresents an integration error handler
-                  to be used as default at runtime
-                properties:
-                  parameters:
-                    description: ErrorHandlerParameters is an unstructured object
-                      representing the configuration parameters available for an error
-                      handler
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  type:
-                    type: string
-                  uri:
-                    type: string
-                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index 2b78d2f..60ac3ba 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -89,21 +89,6 @@ spec:
                     items:
                       type: string
                     type: array
-                  errorHandler:
-                    description: ErrorHandlerSpec respresents an integration error
-                      handler to be used as default at runtime
-                    properties:
-                      parameters:
-                        description: ErrorHandlerParameters is an unstructured object
-                          representing the configuration parameters available for
-                          an error handler
-                        type: object
-                        x-kubernetes-preserve-unknown-fields: true
-                      type:
-                        type: string
-                      uri:
-                        type: string
-                    type: object
                   flows:
                     items:
                       description: Flow is an unstructured object representing a Camel
diff --git a/deploy/olm-catalog/camel-k-dev/1.5.0-snapshot/camel.apache.org_kameletbindings.yaml b/deploy/olm-catalog/camel-k-dev/1.5.0-snapshot/camel.apache.org_kameletbindings.yaml
index c9a8b87..60ac3ba 100644
--- a/deploy/olm-catalog/camel-k-dev/1.5.0-snapshot/camel.apache.org_kameletbindings.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.5.0-snapshot/camel.apache.org_kameletbindings.yaml
@@ -63,6 +63,11 @@ spec:
           spec:
             description: KameletBindingSpec --
             properties:
+              errorHandler:
+                description: ErrorHandler is an optional handler called upon an error
+                  occuring in the integration
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
diff --git a/helm/camel-k/crds/crd-integration.yaml b/helm/camel-k/crds/crd-integration.yaml
index 0b1b88a..96e26b9 100644
--- a/helm/camel-k/crds/crd-integration.yaml
+++ b/helm/camel-k/crds/crd-integration.yaml
@@ -88,21 +88,6 @@ spec:
                 items:
                   type: string
                 type: array
-              errorHandler:
-                description: ErrorHandlerSpec respresents an integration error handler
-                  to be used as default at runtime
-                properties:
-                  parameters:
-                    description: ErrorHandlerParameters is an unstructured object
-                      representing the configuration parameters available for an error
-                      handler
-                    type: object
-                    x-kubernetes-preserve-unknown-fields: true
-                  type:
-                    type: string
-                  uri:
-                    type: string
-                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index 2b78d2f..60ac3ba 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -89,21 +89,6 @@ spec:
                     items:
                       type: string
                     type: array
-                  errorHandler:
-                    description: ErrorHandlerSpec respresents an integration error
-                      handler to be used as default at runtime
-                    properties:
-                      parameters:
-                        description: ErrorHandlerParameters is an unstructured object
-                          representing the configuration parameters available for
-                          an error handler
-                        type: object
-                        x-kubernetes-preserve-unknown-fields: true
-                      type:
-                        type: string
-                      uri:
-                        type: string
-                    type: object
                   flows:
                     items:
                       description: Flow is an unstructured object representing a Camel

[camel-k] 07/30: feat(trait): error handler trait

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 92873431e970b65a1dee3aff8fc8ebd5b07a8fd7
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 20 16:14:41 2021 +0200

    feat(trait): error handler trait
    
    * KameletBinding can specify the error handler type
    * Introduced a trait to parse and create an error handler source type as expected by runtime.
---
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go |  20 ++-
 pkg/controller/kameletbinding/common.go          |  17 +--
 pkg/resources/resources.go                       |   4 +-
 pkg/trait/error_handler.go                       | 162 +++++++++++++++++++++++
 pkg/trait/kamelets.go                            |  48 +++----
 pkg/trait/trait_register.go                      |   1 +
 pkg/trait/trait_test.go                          |   2 +-
 7 files changed, 207 insertions(+), 47 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index b91ed55..367692c 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -33,11 +33,25 @@ type KameletBindingSpec struct {
 	// Sink is the destination of the integration defined by this binding
 	Sink Endpoint `json:"sink,omitempty"`
 	// ErrorHandler is an optional handler called upon an error occuring in the integration
-	ErrorHandler Endpoint `json:"errorHandler,omitempty"`
+	ErrorHandler ErrorHandler `json:"errorHandler,omitempty"`
 	// Steps contains an optional list of intermediate steps that are executed between the Source and the Sink
 	Steps []Endpoint `json:"steps,omitempty"`
 }
 
+type ErrorHandler struct {
+	Endpoint      Endpoint                `json:"endpoint,omitempty"`
+	Type          ErrorHandlerType        `json:"type,omitempty"`
+	Configuration *ErrorHandlerProperties `json:"configuration,omitempty"`
+}
+
+type ErrorHandlerType string
+
+const (
+	ErrorHandlerTypeNone              ErrorHandlerType = "no"
+	ErrorHandlerTypeDefault           ErrorHandlerType = "default"
+	ErrorHandlerTypeDeadLetterChannel ErrorHandlerType = "dead-letter-channel"
+)
+
 // Endpoint represents a source/sink external entity
 type Endpoint struct {
 	// Ref can be used to declare a Kubernetes resource as source/sink endpoint
@@ -59,6 +73,10 @@ const (
 	EndpointTypeErrorHandler EndpointType = "errorHandler"
 )
 
+type ErrorHandlerProperties struct {
+	v1.RawMessage `json:",inline"`
+}
+
 // EndpointProperties is a key/value struct represented as JSON raw to allow numeric/boolean values
 type EndpointProperties struct {
 	v1.RawMessage `json:",inline"`
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index fdeab95..a63780f 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -22,7 +22,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"sort"
-	"strings"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -81,8 +80,8 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
 	var errorHandler *bindings.Binding
-	if kameletbinding.Spec.ErrorHandler.Ref != nil || kameletbinding.Spec.ErrorHandler.URI != nil {
-		errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
+	if kameletbinding.Spec.ErrorHandler.Endpoint.Ref != nil || kameletbinding.Spec.ErrorHandler.Endpoint.URI != nil {
+		errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler.Endpoint)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not determine error handler URI")
 		}
@@ -160,20 +159,14 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	return &it, nil
 }
 
-func setErrorHandlerKamelet(errorHandler *bindings.Binding, kameletSpec v1alpha1.Endpoint) error {
+func setErrorHandlerKamelet(errorHandler *bindings.Binding, errorHandlerSpec v1alpha1.ErrorHandler) error {
 	if errorHandler.ApplicationProperties == nil {
 		errorHandler.ApplicationProperties = make(map[string]string)
 	}
-	if kameletSpec.URI != nil {
-		if !strings.HasPrefix(*kameletSpec.URI, "kamelet") {
-			return fmt.Errorf("Kamelet Binding only supports kamelet as error handler, provided: %s", *kameletSpec.URI)
-		}
 
-		errorHandler.ApplicationProperties["camel.k.default-error-handler"] = *kameletSpec.URI
-		return nil
-	}
+	errorHandler.ApplicationProperties["camel.k.default-error-handler.uri"] = errorHandler.URI
+	errorHandler.ApplicationProperties["camel.k.default-error-handler.type"] = string(errorHandlerSpec.Type)
 
-	errorHandler.ApplicationProperties["camel.k.default-error-handler"] = kameletSpec.Ref.Name
 	return nil
 }
 
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 6b712ac..7603bbb 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -113,9 +113,9 @@ var assets = func() http.FileSystem {
 		"/crd/bases/camel.apache.org_kameletbindings.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kameletbindings.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 55181,
+			uncompressedSize: 68634,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x01\x4b\x8e\xe3\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\x7b\x7e\xed\xa6\x45\x92\xde\xe1\x5e\xdb\x03\x68\x69\x6c\xf3\x22\x91\x3a\x92\x8a\xe3\xef\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x99\x72\xec\x6e\x0a\x88\xc0\x62\x6b\x8b\x1a\xce\x0c\x87\xc3\x99\x21\x3f\xce\x11\x78\xbb\x6b\x07\x47\xf0\x9e\x06\xc8\x24\x86\xa0\x38\xa8\x29\xc2\x59\x42\x82\x29\xc2\x35\x1f\xab\x19\x11\x08\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5d\xff\x6f\xdb\x38\xb2\xff\x3d\x7f\xc5\x20\x39\xa0\x2d\x10\xd9\x71\x92\x76\x77\xfd\x7e\x28\xb2\xc9\xf6\xce\xaf\xdd\x34\xc8\x97\x3b\xdc\x6b\x7b\x00\x2d\x8d\x6d\x5e\x24\x52\x47\x52\x71\xfc\xb6\xfd\xdf\x1f\x48\x4a\xb2\xfc\x45\x12\xe5\xd8\xdd\xf4\x41\x04\x8a\xc6\x16\x35\x9c\x19\x0e\x87\xdf\xe6\x33\x3e\x00\x6f\x7b\x65\xef\x00\x3e\x50\x1f\x99\xc4\x00\x14\x07\x35\x41\x38\x8b\x89\x3f\x41\xb8\xe1\x23\x35\x25\x02\xe1\x1d\x [...]
 		},
 		"/crd/bases/camel.apache.org_kamelets.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kamelets.yaml",
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
new file mode 100644
index 0000000..7101d9e
--- /dev/null
+++ b/pkg/trait/error_handler.go
@@ -0,0 +1,162 @@
+/*
+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"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+// The error handler is a platform trait used to inject Error Handler source into the integration runtime.
+//
+// +camel-k:trait=error-handler
+type errorHandlerTrait struct {
+	BaseTrait `property:",squash"`
+	// Automatically inject all referenced Kamelets and their default configuration (enabled by default)
+	Auto *bool `property:"auto"`
+
+	// TODO move into a struct
+	ErrorHandlerURI  string
+	ErrorHandlerType string
+}
+
+func newErrorHandlerTrait() Trait {
+	return &errorHandlerTrait{
+		BaseTrait: NewBaseTrait("errorHandler", 500),
+	}
+}
+
+// IsPlatformTrait overrides base class method
+func (t *errorHandlerTrait) IsPlatformTrait() bool {
+	return true
+}
+
+func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
+	if t.Enabled != nil && !*t.Enabled {
+		return false, nil
+	}
+
+	if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
+		return false, nil
+	}
+
+	if t.Auto == nil || *t.Auto {
+		if t.ErrorHandlerType == "" {
+			t.ErrorHandlerType = maybeErrorHandler(e.Integration.Configurations())
+			if t.ErrorHandlerType != "" && v1alpha1.ErrorHandlerType(t.ErrorHandlerType) == v1alpha1.ErrorHandlerTypeDeadLetterChannel {
+				t.ErrorHandlerURI = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
+			}
+		}
+	}
+
+	return t.ErrorHandlerType != "", nil
+}
+
+func maybeErrorHandler(properties []v1.ConfigurationSpec) string {
+	for _, property := range properties {
+		if strings.HasPrefix(property.Value, "camel.k.default-error-handler.type=") {
+			split := strings.Split(property.Value, "=")
+			if len(split) > 0 {
+				return split[1]
+			}
+		}
+	}
+
+	return ""
+}
+
+func maybeKameletAsDefaultErrorHandler(properties []v1.ConfigurationSpec) string {
+	for _, property := range properties {
+		if strings.HasPrefix(property.Value, "camel.k.default-error-handler.uri=") {
+			split := strings.Split(property.Value, "=")
+			if len(split) > 0 {
+				return split[1]
+			}
+		}
+	}
+
+	return ""
+}
+
+func (t *errorHandlerTrait) Apply(e *Environment) error {
+
+	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+		if t.ErrorHandlerType != "" {
+			// Possible error handler
+			err := addErrorHandlerAsSource(e, t.ErrorHandlerURI, t.ErrorHandlerType)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func addErrorHandlerAsSource(e *Environment, errorHandlerURI string, errorHandlerType string) error {
+	errorHandlerStatement, err := parseErrorHandler(errorHandlerURI, errorHandlerType)
+	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(`
+			import org.apache.camel.builder.RouteBuilder;
+			public class ErrorHandlerSource extends RouteBuilder {
+			@Override
+			public void configure() throws Exception {
+			  %s
+			  }
+			}
+			`, errorHandlerStatement),
+		},
+		Language: v1.LanguageJavaSource,
+		Type:     v1.SourceTypeErrorHandler,
+	}
+
+	replaced := false
+	for idx, existing := range e.Integration.Status.GeneratedSources {
+		if existing.Name == errorHandlerSource.Name {
+			replaced = true
+			e.Integration.Status.GeneratedSources[idx] = errorHandlerSource
+		}
+	}
+	if !replaced {
+		e.Integration.Status.GeneratedSources = append(e.Integration.Status.GeneratedSources, errorHandlerSource)
+	}
+
+	return nil
+}
+
+func parseErrorHandler(errHandlUri string, errHandlType string) (string, error) {
+	switch errHandlType {
+	case "no":
+		return `errorHandler(noErrorHandler());`, nil
+	case "default":
+		return `errorHandler(defaultErrorHandler());`, nil
+	case "dead-letter-channel":
+		return fmt.Sprintf(`errorHandler(deadLetterChannel("%v"));`, errHandlUri), nil
+	}
+
+	return "", fmt.Errorf("Cannot recognize any error handler of type %s", errHandlType)
+}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 053678d..dd4c3bb 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -47,8 +47,10 @@ type kameletsTrait struct {
 	Auto *bool `property:"auto"`
 	// Comma separated list of Kamelet names to load into the current integration
 	List string `property:"list"`
-	// Kamelet name used as error handler
-	ErrorHandler string `property:"error-handler"`
+
+	// TODO move into a struct
+	ErrorHandlerURI  string
+	ErrorHandlerType string
 }
 
 type configurationKey struct {
@@ -96,8 +98,8 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 	}
 
 	if t.Auto == nil || *t.Auto {
+		var kamelets []string
 		if t.List == "" {
-			var kamelets []string
 			sources, err := kubernetes.ResolveIntegrationSources(e.C, e.Client, e.Integration, e.Resources)
 			if err != nil {
 				return false, err
@@ -108,34 +110,25 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 				return true
 			})
 			sort.Strings(kamelets)
-			t.List = strings.Join(kamelets, ",")
-		}
-		if t.ErrorHandler == "" {
-			t.ErrorHandler = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
 		}
-	}
-
-	return t.declareKamelets(), nil
-}
-
-func maybeKameletAsDefaultErrorHandler(properties []v1.ConfigurationSpec) string {
-	for _, property := range properties {
-		if strings.HasPrefix(property.Value, "camel.k.default-error-handler=") {
-			split := strings.Split(property.Value, "=")
-			if len(split) > 0 {
-				if strings.HasPrefix(split[1], "kamelet:") {
-					return extractKamelet(split[1])
+		if t.ErrorHandlerType == "" {
+			t.ErrorHandlerType = maybeErrorHandler(e.Integration.Configurations())
+			if t.ErrorHandlerType != "" && v1alpha1.ErrorHandlerType(t.ErrorHandlerType) == v1alpha1.ErrorHandlerTypeDeadLetterChannel {
+				t.ErrorHandlerURI = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
+				if strings.HasPrefix(t.ErrorHandlerURI, "kamelet:") {
+					kamelets = append(kamelets, extractKamelet(t.ErrorHandlerURI))
 				}
-				return split[1]
 			}
 		}
+
+		t.List = strings.Join(kamelets, ",")
 	}
 
-	return ""
+	return t.declaredKamelets(), nil
 }
 
-func (t *kameletsTrait) declareKamelets() bool {
-	return len(t.getKameletKeys()) > 0 || t.ErrorHandler != ""
+func (t *kameletsTrait) declaredKamelets() bool {
+	return len(t.getKameletKeys()) > 0
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
@@ -156,7 +149,7 @@ func (t *kameletsTrait) Apply(e *Environment) error {
 }
 
 func (t *kameletsTrait) addKamelets(e *Environment) error {
-	if t.declareKamelets() {
+	if t.declaredKamelets() {
 		repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
 		if err != nil {
 			return err
@@ -169,13 +162,6 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
 				return err
 			}
 		}
-		if t.ErrorHandler != "" {
-			// Possible error handler
-			err = initializeKamelet(repo, e, t.ErrorHandler, t, v1.SourceTypeErrorHandler)
-			if err != nil {
-				return err
-			}
-		}
 
 		// resort dependencies
 		sort.Strings(e.Integration.Status.Dependencies)
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index 4c06b37..30e89bd 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -26,6 +26,7 @@ func init() {
 	AddToTraits(newOpenAPITrait)
 	AddToTraits(newKnativeTrait)
 	AddToTraits(newKameletsTrait)
+	AddToTraits(newErrorHandlerTrait)
 	AddToTraits(newDependenciesTrait)
 	AddToTraits(newBuilderTrait)
 	AddToTraits(newQuarkusTrait)
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index f8f75af..b8fdca8 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -507,7 +507,7 @@ func TestOnlySomeTraitsInfluenceBuild(t *testing.T) {
 
 func TestOnlySomeTraitsArePlatform(t *testing.T) {
 	c := NewTraitTestCatalog()
-	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "kamelets", "openapi", "owner", "platform", "quarkus"}
+	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "errorHandler", "kamelets", "openapi", "owner", "platform", "quarkus"}
 
 	for _, trait := range c.allTraits() {
 		if trait.IsPlatformTrait() {

[camel-k] 16/30: chore(controller): error handler unit test

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit d922c4a3d12a602772450bd836e2a60e65fee1a2
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Thu Apr 22 16:47:36 2021 +0200

    chore(controller): error handler unit test
---
 pkg/apis/camel/v1alpha1/error_handler_types.go     |  7 +-
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |  4 --
 .../kameletbinding/error_handler_test.go           | 77 ++++++++++++++++++++++
 3 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/error_handler_types.go b/pkg/apis/camel/v1alpha1/error_handler_types.go
index a6b15b1..df46324 100644
--- a/pkg/apis/camel/v1alpha1/error_handler_types.go
+++ b/pkg/apis/camel/v1alpha1/error_handler_types.go
@@ -21,11 +21,16 @@ import (
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-// ErrorHandler represent an unstructured object for an error handler
+// ErrorHandler represents an unstructured object for an error handler
 type ErrorHandler struct {
 	v1.RawMessage `json:",omitempty"`
 }
 
+// ErrorHandlerProperties represent an unstructured object for error handler parameters
+type ErrorHandlerProperties struct {
+	v1.RawMessage `json:",inline"`
+}
+
 // AbstractErrorHandler is a generic interface that represent any type of error handler specification
 type AbstractErrorHandler interface {
 	Type() ErrorHandlerType
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index 5a279e1..62e8079 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -59,10 +59,6 @@ const (
 	EndpointTypeErrorHandler EndpointType = "errorHandler"
 )
 
-type ErrorHandlerProperties struct {
-	v1.RawMessage `json:",inline"`
-}
-
 // EndpointProperties is a key/value struct represented as JSON raw to allow numeric/boolean values
 type EndpointProperties struct {
 	v1.RawMessage `json:",inline"`
diff --git a/pkg/controller/kameletbinding/error_handler_test.go b/pkg/controller/kameletbinding/error_handler_test.go
new file mode 100644
index 0000000..1600707
--- /dev/null
+++ b/pkg/controller/kameletbinding/error_handler_test.go
@@ -0,0 +1,77 @@
+/*
+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 kameletbinding
+
+import (
+	"testing"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParseErrorHandlerNoneDoesSucceed(t *testing.T) {
+	noErrorHandler, err := parseErrorHandler(
+		[]byte(`{"none": null}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeNone, noErrorHandler.Type())
+}
+
+func TestParseErrorHandlerLogDoesSucceed(t *testing.T) {
+	logErrorHandler, err := parseErrorHandler(
+		[]byte(`{"log": null}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeLog, logErrorHandler.Type())
+}
+
+func TestParseErrorHandlerLogWithParametersDoesSucceed(t *testing.T) {
+	logErrorHandler, err := parseErrorHandler(
+		[]byte(`{"log": {"parameters": [{"param1": "value1"}, {"param2": "value2"}]}}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeLog, logErrorHandler.Type())
+	assert.NotNil(t, logErrorHandler.Params())
+}
+
+func TestParseErrorHandlerDLCDoesSucceed(t *testing.T) {
+	dlcErrorHandler, err := parseErrorHandler(
+		[]byte(`{"dead-letter-channel": {"endpoint": {"uri": "someUri"}}}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeDeadLetterChannel, dlcErrorHandler.Type())
+	assert.Equal(t, "someUri", *dlcErrorHandler.Endpoint().URI)
+}
+
+func TestParseErrorHandlerDLCWithParametersDoesSucceed(t *testing.T) {
+	dlcErrorHandler, err := parseErrorHandler(
+		[]byte(`{
+			"dead-letter-channel": {
+				"endpoint": {
+					"uri": "someUri"
+					}, 
+				"parameters": 
+					[{"param1": "value1"}]
+			}
+		}`),
+	)
+	assert.Nil(t, err)
+	assert.Equal(t, v1alpha1.ErrorHandlerTypeDeadLetterChannel, dlcErrorHandler.Type())
+	assert.Equal(t, "someUri", *dlcErrorHandler.Endpoint().URI)
+	assert.NotNil(t, dlcErrorHandler.Params())
+}

[camel-k] 11/30: refactor(crd): updated crd after error-handler

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 5eaff76b0ecc0e2d41c90dbc6f26b203af3ab49e
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 15:15:45 2021 +0200

    refactor(crd): updated crd after error-handler
---
 .../crd/bases/camel.apache.org_integrations.yaml   |  13 +
 .../bases/camel.apache.org_kameletbindings.yaml    | 413 +++++++++++----------
 .../1.4.0/camel.apache.org_integrations.yaml       |  13 +
 .../1.4.0/camel.apache.org_kameletbindings.yaml    | 413 +++++++++++----------
 helm/camel-k/crds/crd-integration.yaml             |  13 +
 helm/camel-k/crds/crd-kamelet-binding.yaml         | 413 +++++++++++----------
 6 files changed, 699 insertions(+), 579 deletions(-)

diff --git a/config/crd/bases/camel.apache.org_integrations.yaml b/config/crd/bases/camel.apache.org_integrations.yaml
index 96e26b9..c838f1f 100644
--- a/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/config/crd/bases/camel.apache.org_integrations.yaml
@@ -88,6 +88,19 @@ spec:
                 items:
                   type: string
                 type: array
+              errorHandler:
+                description: ErrorHandlerSpec respresents an integration error handler
+                  to be used as default at runtime
+                properties:
+                  configuration:
+                    description: ErrorHandlerConfiguration --
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  type:
+                    type: string
+                  uri:
+                    type: string
+                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index 7c43c55..046549c 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -67,214 +67,228 @@ spec:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
                 properties:
-                  properties:
-                    description: Properties are a key value representation of endpoint
-                      properties
+                  configuration:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
-                  ref:
-                    description: Ref can be used to declare a Kubernetes resource
-                      as source/sink endpoint
+                  endpoint:
+                    description: Endpoint represents a source/sink external entity
                     properties:
-                      apiVersion:
-                        description: API version of the referent.
-                        type: string
-                      fieldPath:
-                        description: 'If referring to a piece of an object instead
-                          of an entire object, this string should contain a valid
-                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                          For example, if the object reference is to a container within
-                          a pod, this would take on a value like: "spec.containers{name}"
-                          (where "name" refers to the name of the container that triggered
-                          the event) or if no container name is specified "spec.containers[2]"
-                          (container with index 2 in this pod). This syntax is chosen
-                          only to have some well-defined way of referencing a part
-                          of an object. TODO: this design is not final and this field
-                          is subject to change in the future.'
-                        type: string
-                      kind:
-                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                        type: string
-                      name:
-                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                        type: string
-                      namespace:
-                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                        type: string
-                      resourceVersion:
-                        description: 'Specific resourceVersion to which this reference
-                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                        type: string
-                      uid:
-                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                        type: string
-                    type: object
-                  types:
-                    additionalProperties:
                       properties:
-                        mediaType:
-                          type: string
-                        schema:
-                          description: JSONSchemaProps is a JSON-Schema following
-                            Specification Draft 4 (http://json-schema.org/).
+                        description: Properties are a key value representation of
+                          endpoint properties
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      ref:
+                        description: Ref can be used to declare a Kubernetes resource
+                          as source/sink endpoint
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          fieldPath:
+                            description: 'If referring to a piece of an object instead
+                              of an entire object, this string should contain a valid
+                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                              For example, if the object reference is to a container
+                              within a pod, this would take on a value like: "spec.containers{name}"
+                              (where "name" refers to the name of the container that
+                              triggered the event) or if no container name is specified
+                              "spec.containers[2]" (container with index 2 in this
+                              pod). This syntax is chosen only to have some well-defined
+                              way of referencing a part of an object. TODO: this design
+                              is not final and this field is subject to change in
+                              the future.'
+                            type: string
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          resourceVersion:
+                            description: 'Specific resourceVersion to which this reference
+                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                            type: string
+                          uid:
+                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                            type: string
+                        type: object
+                      types:
+                        additionalProperties:
                           properties:
-                            $schema:
-                              description: JSONSchemaURL represents a schema url.
+                            mediaType:
                               type: string
-                            description:
-                              type: string
-                            example:
-                              description: 'JSON represents any valid JSON value.
-                                These types are supported: bool, int64, float64, string,
-                                []interface{}, map[string]interface{} and nil.'
-                              x-kubernetes-preserve-unknown-fields: true
-                            externalDocs:
-                              description: ExternalDocumentation allows referencing
-                                an external resource for extended documentation.
+                            schema:
+                              description: JSONSchemaProps is a JSON-Schema following
+                                Specification Draft 4 (http://json-schema.org/).
                               properties:
+                                $schema:
+                                  description: JSONSchemaURL represents a schema url.
+                                  type: string
                                 description:
                                   type: string
-                                url:
+                                example:
+                                  description: 'JSON represents any valid JSON value.
+                                    These types are supported: bool, int64, float64,
+                                    string, []interface{}, map[string]interface{}
+                                    and nil.'
+                                  x-kubernetes-preserve-unknown-fields: true
+                                externalDocs:
+                                  description: ExternalDocumentation allows referencing
+                                    an external resource for extended documentation.
+                                  properties:
+                                    description:
+                                      type: string
+                                    url:
+                                      type: string
+                                  type: object
+                                id:
                                   type: string
-                              type: object
-                            id:
-                              type: string
-                            properties:
-                              additionalProperties:
                                 properties:
-                                  default:
-                                    description: default is a default value for undefined
-                                      object fields.
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  description:
-                                    type: string
-                                  enum:
-                                    items:
-                                      description: 'JSON represents any valid JSON
-                                        value. These types are supported: bool, int64,
-                                        float64, string, []interface{}, map[string]interface{}
-                                        and nil.'
-                                      x-kubernetes-preserve-unknown-fields: true
-                                    type: array
-                                  example:
-                                    description: 'JSON represents any valid JSON value.
-                                      These types are supported: bool, int64, float64,
-                                      string, []interface{}, map[string]interface{}
-                                      and nil.'
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  exclusiveMaximum:
-                                    type: boolean
-                                  exclusiveMinimum:
-                                    type: boolean
-                                  format:
-                                    description: "format is an OpenAPI v3 format string.
-                                      Unknown formats are ignored. The following formats
-                                      are validated: \n - bsonobjectid: a bson object
-                                      ID, i.e. a 24 characters hex string - uri: an
-                                      URI as parsed by Golang net/url.ParseRequestURI
-                                      - email: an email address as parsed by Golang
-                                      net/mail.ParseAddress - hostname: a valid representation
-                                      for an Internet host name, as defined by RFC
-                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
-                                      IP as parsed by Golang net.ParseIP - ipv6: an
-                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
-                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
-                                      a MAC address as parsed by Golang net.ParseMAC
-                                      - uuid: an UUID that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid3: an UUID3 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid4: an UUID4 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - uuid5: an UUID5 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - isbn: an ISBN10 or ISBN13 number string like
-                                      \"0321751043\" or \"978-0321751041\" - isbn10:
-                                      an ISBN10 number string like \"0321751043\"
-                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                      - creditcard: a credit card number defined by
-                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                      with any non digit characters mixed in - ssn:
-                                      a U.S. social security number following the
-                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
-                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
-                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                      - rgbcolor: an RGB color code like rgb like
-                                      \"rgb(255,255,2559\" - byte: base64 encoded
-                                      binary data - password: any kind of string -
-                                      date: a date string like \"2006-01-02\" as defined
-                                      by full-date in RFC3339 - duration: a duration
-                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
-                                      or compatible with Scala duration format - datetime:
-                                      a date time string like \"2014-12-15T19:30:20.000Z\"
-                                      as defined by date-time in RFC3339."
-                                    type: string
-                                  id:
-                                    type: string
-                                  maxItems:
-                                    format: int64
-                                    type: integer
-                                  maxLength:
-                                    format: int64
-                                    type: integer
-                                  maxProperties:
-                                    format: int64
-                                    type: integer
-                                  maximum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  minItems:
-                                    format: int64
-                                    type: integer
-                                  minLength:
-                                    format: int64
-                                    type: integer
-                                  minProperties:
-                                    format: int64
-                                    type: integer
-                                  minimum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  multipleOf:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  nullable:
-                                    type: boolean
-                                  pattern:
-                                    type: string
-                                  title:
-                                    type: string
-                                  type:
+                                  additionalProperties:
+                                    properties:
+                                      default:
+                                        description: default is a default value for
+                                          undefined object fields.
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      description:
+                                        type: string
+                                      enum:
+                                        items:
+                                          description: 'JSON represents any valid
+                                            JSON value. These types are supported:
+                                            bool, int64, float64, string, []interface{},
+                                            map[string]interface{} and nil.'
+                                          x-kubernetes-preserve-unknown-fields: true
+                                        type: array
+                                      example:
+                                        description: 'JSON represents any valid JSON
+                                          value. These types are supported: bool,
+                                          int64, float64, string, []interface{}, map[string]interface{}
+                                          and nil.'
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      exclusiveMaximum:
+                                        type: boolean
+                                      exclusiveMinimum:
+                                        type: boolean
+                                      format:
+                                        description: "format is an OpenAPI v3 format
+                                          string. Unknown formats are ignored. The
+                                          following formats are validated: \n - bsonobjectid:
+                                          a bson object ID, i.e. a 24 characters hex
+                                          string - uri: an URI as parsed by Golang
+                                          net/url.ParseRequestURI - email: an email
+                                          address as parsed by Golang net/mail.ParseAddress
+                                          - hostname: a valid representation for an
+                                          Internet host name, as defined by RFC 1034,
+                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
+                                          as parsed by Golang net.ParseIP - ipv6:
+                                          an IPv6 IP as parsed by Golang net.ParseIP
+                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
+                                          - mac: a MAC address as parsed by Golang
+                                          net.ParseMAC - uuid: an UUID that allows
+                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid3: an UUID3 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid4: an UUID4 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - uuid5: an UUID5 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - isbn: an ISBN10 or ISBN13 number string
+                                          like \"0321751043\" or \"978-0321751041\"
+                                          - isbn10: an ISBN10 number string like \"0321751043\"
+                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                          - creditcard: a credit card number defined
+                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                          with any non digit characters mixed in -
+                                          ssn: a U.S. social security number following
+                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
+                                          - hexcolor: an hexadecimal color code like
+                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                          - rgbcolor: an RGB color code like rgb like
+                                          \"rgb(255,255,2559\" - byte: base64 encoded
+                                          binary data - password: any kind of string
+                                          - date: a date string like \"2006-01-02\"
+                                          as defined by full-date in RFC3339 - duration:
+                                          a duration string like \"22 ns\" as parsed
+                                          by Golang time.ParseDuration or compatible
+                                          with Scala duration format - datetime: a
+                                          date time string like \"2014-12-15T19:30:20.000Z\"
+                                          as defined by date-time in RFC3339."
+                                        type: string
+                                      id:
+                                        type: string
+                                      maxItems:
+                                        format: int64
+                                        type: integer
+                                      maxLength:
+                                        format: int64
+                                        type: integer
+                                      maxProperties:
+                                        format: int64
+                                        type: integer
+                                      maximum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      minItems:
+                                        format: int64
+                                        type: integer
+                                      minLength:
+                                        format: int64
+                                        type: integer
+                                      minProperties:
+                                        format: int64
+                                        type: integer
+                                      minimum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      multipleOf:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      nullable:
+                                        type: boolean
+                                      pattern:
+                                        type: string
+                                      title:
+                                        type: string
+                                      type:
+                                        type: string
+                                      uniqueItems:
+                                        type: boolean
+                                      x-descriptors:
+                                        description: The list of descriptors that
+                                          determine which UI components to use on
+                                          different views
+                                        items:
+                                          type: string
+                                        type: array
+                                    type: object
+                                  type: object
+                                required:
+                                  items:
                                     type: string
-                                  uniqueItems:
-                                    type: boolean
-                                  x-descriptors:
-                                    description: The list of descriptors that determine
-                                      which UI components to use on different views
-                                    items:
-                                      type: string
-                                    type: array
-                                type: object
+                                  type: array
+                                title:
+                                  type: string
+                                type:
+                                  type: string
                               type: object
-                            required:
-                              items:
-                                type: string
-                              type: array
-                            title:
-                              type: string
-                            type:
-                              type: string
                           type: object
-                      type: object
-                    description: Types defines the schema of the data produced/consumed
-                      by the endpoint
+                        description: Types defines the schema of the data produced/consumed
+                          by the endpoint
+                        type: object
+                      uri:
+                        description: URI can alternatively be used to specify the
+                          (Camel) endpoint explicitly
+                        type: string
                     type: object
-                  uri:
-                    description: URI can alternatively be used to specify the (Camel)
-                      endpoint explicitly
+                  type:
                     type: string
                 type: object
               integration:
@@ -298,6 +312,19 @@ spec:
                     items:
                       type: string
                     type: array
+                  errorHandler:
+                    description: ErrorHandlerSpec respresents an integration error
+                      handler to be used as default at runtime
+                    properties:
+                      configuration:
+                        description: ErrorHandlerConfiguration --
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      type:
+                        type: string
+                      uri:
+                        type: string
+                    type: object
                   flows:
                     items:
                       description: Flow is an unstructured object representing a Camel
diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
index 96e26b9..c838f1f 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_integrations.yaml
@@ -88,6 +88,19 @@ spec:
                 items:
                   type: string
                 type: array
+              errorHandler:
+                description: ErrorHandlerSpec respresents an integration error handler
+                  to be used as default at runtime
+                properties:
+                  configuration:
+                    description: ErrorHandlerConfiguration --
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  type:
+                    type: string
+                  uri:
+                    type: string
+                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
index 7c43c55..046549c 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
@@ -67,214 +67,228 @@ spec:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
                 properties:
-                  properties:
-                    description: Properties are a key value representation of endpoint
-                      properties
+                  configuration:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
-                  ref:
-                    description: Ref can be used to declare a Kubernetes resource
-                      as source/sink endpoint
+                  endpoint:
+                    description: Endpoint represents a source/sink external entity
                     properties:
-                      apiVersion:
-                        description: API version of the referent.
-                        type: string
-                      fieldPath:
-                        description: 'If referring to a piece of an object instead
-                          of an entire object, this string should contain a valid
-                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                          For example, if the object reference is to a container within
-                          a pod, this would take on a value like: "spec.containers{name}"
-                          (where "name" refers to the name of the container that triggered
-                          the event) or if no container name is specified "spec.containers[2]"
-                          (container with index 2 in this pod). This syntax is chosen
-                          only to have some well-defined way of referencing a part
-                          of an object. TODO: this design is not final and this field
-                          is subject to change in the future.'
-                        type: string
-                      kind:
-                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                        type: string
-                      name:
-                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                        type: string
-                      namespace:
-                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                        type: string
-                      resourceVersion:
-                        description: 'Specific resourceVersion to which this reference
-                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                        type: string
-                      uid:
-                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                        type: string
-                    type: object
-                  types:
-                    additionalProperties:
                       properties:
-                        mediaType:
-                          type: string
-                        schema:
-                          description: JSONSchemaProps is a JSON-Schema following
-                            Specification Draft 4 (http://json-schema.org/).
+                        description: Properties are a key value representation of
+                          endpoint properties
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      ref:
+                        description: Ref can be used to declare a Kubernetes resource
+                          as source/sink endpoint
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          fieldPath:
+                            description: 'If referring to a piece of an object instead
+                              of an entire object, this string should contain a valid
+                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                              For example, if the object reference is to a container
+                              within a pod, this would take on a value like: "spec.containers{name}"
+                              (where "name" refers to the name of the container that
+                              triggered the event) or if no container name is specified
+                              "spec.containers[2]" (container with index 2 in this
+                              pod). This syntax is chosen only to have some well-defined
+                              way of referencing a part of an object. TODO: this design
+                              is not final and this field is subject to change in
+                              the future.'
+                            type: string
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          resourceVersion:
+                            description: 'Specific resourceVersion to which this reference
+                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                            type: string
+                          uid:
+                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                            type: string
+                        type: object
+                      types:
+                        additionalProperties:
                           properties:
-                            $schema:
-                              description: JSONSchemaURL represents a schema url.
+                            mediaType:
                               type: string
-                            description:
-                              type: string
-                            example:
-                              description: 'JSON represents any valid JSON value.
-                                These types are supported: bool, int64, float64, string,
-                                []interface{}, map[string]interface{} and nil.'
-                              x-kubernetes-preserve-unknown-fields: true
-                            externalDocs:
-                              description: ExternalDocumentation allows referencing
-                                an external resource for extended documentation.
+                            schema:
+                              description: JSONSchemaProps is a JSON-Schema following
+                                Specification Draft 4 (http://json-schema.org/).
                               properties:
+                                $schema:
+                                  description: JSONSchemaURL represents a schema url.
+                                  type: string
                                 description:
                                   type: string
-                                url:
+                                example:
+                                  description: 'JSON represents any valid JSON value.
+                                    These types are supported: bool, int64, float64,
+                                    string, []interface{}, map[string]interface{}
+                                    and nil.'
+                                  x-kubernetes-preserve-unknown-fields: true
+                                externalDocs:
+                                  description: ExternalDocumentation allows referencing
+                                    an external resource for extended documentation.
+                                  properties:
+                                    description:
+                                      type: string
+                                    url:
+                                      type: string
+                                  type: object
+                                id:
                                   type: string
-                              type: object
-                            id:
-                              type: string
-                            properties:
-                              additionalProperties:
                                 properties:
-                                  default:
-                                    description: default is a default value for undefined
-                                      object fields.
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  description:
-                                    type: string
-                                  enum:
-                                    items:
-                                      description: 'JSON represents any valid JSON
-                                        value. These types are supported: bool, int64,
-                                        float64, string, []interface{}, map[string]interface{}
-                                        and nil.'
-                                      x-kubernetes-preserve-unknown-fields: true
-                                    type: array
-                                  example:
-                                    description: 'JSON represents any valid JSON value.
-                                      These types are supported: bool, int64, float64,
-                                      string, []interface{}, map[string]interface{}
-                                      and nil.'
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  exclusiveMaximum:
-                                    type: boolean
-                                  exclusiveMinimum:
-                                    type: boolean
-                                  format:
-                                    description: "format is an OpenAPI v3 format string.
-                                      Unknown formats are ignored. The following formats
-                                      are validated: \n - bsonobjectid: a bson object
-                                      ID, i.e. a 24 characters hex string - uri: an
-                                      URI as parsed by Golang net/url.ParseRequestURI
-                                      - email: an email address as parsed by Golang
-                                      net/mail.ParseAddress - hostname: a valid representation
-                                      for an Internet host name, as defined by RFC
-                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
-                                      IP as parsed by Golang net.ParseIP - ipv6: an
-                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
-                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
-                                      a MAC address as parsed by Golang net.ParseMAC
-                                      - uuid: an UUID that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid3: an UUID3 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid4: an UUID4 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - uuid5: an UUID5 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - isbn: an ISBN10 or ISBN13 number string like
-                                      \"0321751043\" or \"978-0321751041\" - isbn10:
-                                      an ISBN10 number string like \"0321751043\"
-                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                      - creditcard: a credit card number defined by
-                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                      with any non digit characters mixed in - ssn:
-                                      a U.S. social security number following the
-                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
-                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
-                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                      - rgbcolor: an RGB color code like rgb like
-                                      \"rgb(255,255,2559\" - byte: base64 encoded
-                                      binary data - password: any kind of string -
-                                      date: a date string like \"2006-01-02\" as defined
-                                      by full-date in RFC3339 - duration: a duration
-                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
-                                      or compatible with Scala duration format - datetime:
-                                      a date time string like \"2014-12-15T19:30:20.000Z\"
-                                      as defined by date-time in RFC3339."
-                                    type: string
-                                  id:
-                                    type: string
-                                  maxItems:
-                                    format: int64
-                                    type: integer
-                                  maxLength:
-                                    format: int64
-                                    type: integer
-                                  maxProperties:
-                                    format: int64
-                                    type: integer
-                                  maximum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  minItems:
-                                    format: int64
-                                    type: integer
-                                  minLength:
-                                    format: int64
-                                    type: integer
-                                  minProperties:
-                                    format: int64
-                                    type: integer
-                                  minimum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  multipleOf:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  nullable:
-                                    type: boolean
-                                  pattern:
-                                    type: string
-                                  title:
-                                    type: string
-                                  type:
+                                  additionalProperties:
+                                    properties:
+                                      default:
+                                        description: default is a default value for
+                                          undefined object fields.
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      description:
+                                        type: string
+                                      enum:
+                                        items:
+                                          description: 'JSON represents any valid
+                                            JSON value. These types are supported:
+                                            bool, int64, float64, string, []interface{},
+                                            map[string]interface{} and nil.'
+                                          x-kubernetes-preserve-unknown-fields: true
+                                        type: array
+                                      example:
+                                        description: 'JSON represents any valid JSON
+                                          value. These types are supported: bool,
+                                          int64, float64, string, []interface{}, map[string]interface{}
+                                          and nil.'
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      exclusiveMaximum:
+                                        type: boolean
+                                      exclusiveMinimum:
+                                        type: boolean
+                                      format:
+                                        description: "format is an OpenAPI v3 format
+                                          string. Unknown formats are ignored. The
+                                          following formats are validated: \n - bsonobjectid:
+                                          a bson object ID, i.e. a 24 characters hex
+                                          string - uri: an URI as parsed by Golang
+                                          net/url.ParseRequestURI - email: an email
+                                          address as parsed by Golang net/mail.ParseAddress
+                                          - hostname: a valid representation for an
+                                          Internet host name, as defined by RFC 1034,
+                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
+                                          as parsed by Golang net.ParseIP - ipv6:
+                                          an IPv6 IP as parsed by Golang net.ParseIP
+                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
+                                          - mac: a MAC address as parsed by Golang
+                                          net.ParseMAC - uuid: an UUID that allows
+                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid3: an UUID3 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid4: an UUID4 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - uuid5: an UUID5 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - isbn: an ISBN10 or ISBN13 number string
+                                          like \"0321751043\" or \"978-0321751041\"
+                                          - isbn10: an ISBN10 number string like \"0321751043\"
+                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                          - creditcard: a credit card number defined
+                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                          with any non digit characters mixed in -
+                                          ssn: a U.S. social security number following
+                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
+                                          - hexcolor: an hexadecimal color code like
+                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                          - rgbcolor: an RGB color code like rgb like
+                                          \"rgb(255,255,2559\" - byte: base64 encoded
+                                          binary data - password: any kind of string
+                                          - date: a date string like \"2006-01-02\"
+                                          as defined by full-date in RFC3339 - duration:
+                                          a duration string like \"22 ns\" as parsed
+                                          by Golang time.ParseDuration or compatible
+                                          with Scala duration format - datetime: a
+                                          date time string like \"2014-12-15T19:30:20.000Z\"
+                                          as defined by date-time in RFC3339."
+                                        type: string
+                                      id:
+                                        type: string
+                                      maxItems:
+                                        format: int64
+                                        type: integer
+                                      maxLength:
+                                        format: int64
+                                        type: integer
+                                      maxProperties:
+                                        format: int64
+                                        type: integer
+                                      maximum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      minItems:
+                                        format: int64
+                                        type: integer
+                                      minLength:
+                                        format: int64
+                                        type: integer
+                                      minProperties:
+                                        format: int64
+                                        type: integer
+                                      minimum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      multipleOf:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      nullable:
+                                        type: boolean
+                                      pattern:
+                                        type: string
+                                      title:
+                                        type: string
+                                      type:
+                                        type: string
+                                      uniqueItems:
+                                        type: boolean
+                                      x-descriptors:
+                                        description: The list of descriptors that
+                                          determine which UI components to use on
+                                          different views
+                                        items:
+                                          type: string
+                                        type: array
+                                    type: object
+                                  type: object
+                                required:
+                                  items:
                                     type: string
-                                  uniqueItems:
-                                    type: boolean
-                                  x-descriptors:
-                                    description: The list of descriptors that determine
-                                      which UI components to use on different views
-                                    items:
-                                      type: string
-                                    type: array
-                                type: object
+                                  type: array
+                                title:
+                                  type: string
+                                type:
+                                  type: string
                               type: object
-                            required:
-                              items:
-                                type: string
-                              type: array
-                            title:
-                              type: string
-                            type:
-                              type: string
                           type: object
-                      type: object
-                    description: Types defines the schema of the data produced/consumed
-                      by the endpoint
+                        description: Types defines the schema of the data produced/consumed
+                          by the endpoint
+                        type: object
+                      uri:
+                        description: URI can alternatively be used to specify the
+                          (Camel) endpoint explicitly
+                        type: string
                     type: object
-                  uri:
-                    description: URI can alternatively be used to specify the (Camel)
-                      endpoint explicitly
+                  type:
                     type: string
                 type: object
               integration:
@@ -298,6 +312,19 @@ spec:
                     items:
                       type: string
                     type: array
+                  errorHandler:
+                    description: ErrorHandlerSpec respresents an integration error
+                      handler to be used as default at runtime
+                    properties:
+                      configuration:
+                        description: ErrorHandlerConfiguration --
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      type:
+                        type: string
+                      uri:
+                        type: string
+                    type: object
                   flows:
                     items:
                       description: Flow is an unstructured object representing a Camel
diff --git a/helm/camel-k/crds/crd-integration.yaml b/helm/camel-k/crds/crd-integration.yaml
index 96e26b9..c838f1f 100644
--- a/helm/camel-k/crds/crd-integration.yaml
+++ b/helm/camel-k/crds/crd-integration.yaml
@@ -88,6 +88,19 @@ spec:
                 items:
                   type: string
                 type: array
+              errorHandler:
+                description: ErrorHandlerSpec respresents an integration error handler
+                  to be used as default at runtime
+                properties:
+                  configuration:
+                    description: ErrorHandlerConfiguration --
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  type:
+                    type: string
+                  uri:
+                    type: string
+                type: object
               flows:
                 items:
                   description: Flow is an unstructured object representing a Camel
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index 7c43c55..046549c 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -67,214 +67,228 @@ spec:
                 description: ErrorHandler is an optional handler called upon an error
                   occuring in the integration
                 properties:
-                  properties:
-                    description: Properties are a key value representation of endpoint
-                      properties
+                  configuration:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
-                  ref:
-                    description: Ref can be used to declare a Kubernetes resource
-                      as source/sink endpoint
+                  endpoint:
+                    description: Endpoint represents a source/sink external entity
                     properties:
-                      apiVersion:
-                        description: API version of the referent.
-                        type: string
-                      fieldPath:
-                        description: 'If referring to a piece of an object instead
-                          of an entire object, this string should contain a valid
-                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
-                          For example, if the object reference is to a container within
-                          a pod, this would take on a value like: "spec.containers{name}"
-                          (where "name" refers to the name of the container that triggered
-                          the event) or if no container name is specified "spec.containers[2]"
-                          (container with index 2 in this pod). This syntax is chosen
-                          only to have some well-defined way of referencing a part
-                          of an object. TODO: this design is not final and this field
-                          is subject to change in the future.'
-                        type: string
-                      kind:
-                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                        type: string
-                      name:
-                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                        type: string
-                      namespace:
-                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                        type: string
-                      resourceVersion:
-                        description: 'Specific resourceVersion to which this reference
-                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
-                        type: string
-                      uid:
-                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
-                        type: string
-                    type: object
-                  types:
-                    additionalProperties:
                       properties:
-                        mediaType:
-                          type: string
-                        schema:
-                          description: JSONSchemaProps is a JSON-Schema following
-                            Specification Draft 4 (http://json-schema.org/).
+                        description: Properties are a key value representation of
+                          endpoint properties
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      ref:
+                        description: Ref can be used to declare a Kubernetes resource
+                          as source/sink endpoint
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          fieldPath:
+                            description: 'If referring to a piece of an object instead
+                              of an entire object, this string should contain a valid
+                              JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                              For example, if the object reference is to a container
+                              within a pod, this would take on a value like: "spec.containers{name}"
+                              (where "name" refers to the name of the container that
+                              triggered the event) or if no container name is specified
+                              "spec.containers[2]" (container with index 2 in this
+                              pod). This syntax is chosen only to have some well-defined
+                              way of referencing a part of an object. TODO: this design
+                              is not final and this field is subject to change in
+                              the future.'
+                            type: string
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          resourceVersion:
+                            description: 'Specific resourceVersion to which this reference
+                              is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                            type: string
+                          uid:
+                            description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                            type: string
+                        type: object
+                      types:
+                        additionalProperties:
                           properties:
-                            $schema:
-                              description: JSONSchemaURL represents a schema url.
+                            mediaType:
                               type: string
-                            description:
-                              type: string
-                            example:
-                              description: 'JSON represents any valid JSON value.
-                                These types are supported: bool, int64, float64, string,
-                                []interface{}, map[string]interface{} and nil.'
-                              x-kubernetes-preserve-unknown-fields: true
-                            externalDocs:
-                              description: ExternalDocumentation allows referencing
-                                an external resource for extended documentation.
+                            schema:
+                              description: JSONSchemaProps is a JSON-Schema following
+                                Specification Draft 4 (http://json-schema.org/).
                               properties:
+                                $schema:
+                                  description: JSONSchemaURL represents a schema url.
+                                  type: string
                                 description:
                                   type: string
-                                url:
+                                example:
+                                  description: 'JSON represents any valid JSON value.
+                                    These types are supported: bool, int64, float64,
+                                    string, []interface{}, map[string]interface{}
+                                    and nil.'
+                                  x-kubernetes-preserve-unknown-fields: true
+                                externalDocs:
+                                  description: ExternalDocumentation allows referencing
+                                    an external resource for extended documentation.
+                                  properties:
+                                    description:
+                                      type: string
+                                    url:
+                                      type: string
+                                  type: object
+                                id:
                                   type: string
-                              type: object
-                            id:
-                              type: string
-                            properties:
-                              additionalProperties:
                                 properties:
-                                  default:
-                                    description: default is a default value for undefined
-                                      object fields.
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  description:
-                                    type: string
-                                  enum:
-                                    items:
-                                      description: 'JSON represents any valid JSON
-                                        value. These types are supported: bool, int64,
-                                        float64, string, []interface{}, map[string]interface{}
-                                        and nil.'
-                                      x-kubernetes-preserve-unknown-fields: true
-                                    type: array
-                                  example:
-                                    description: 'JSON represents any valid JSON value.
-                                      These types are supported: bool, int64, float64,
-                                      string, []interface{}, map[string]interface{}
-                                      and nil.'
-                                    x-kubernetes-preserve-unknown-fields: true
-                                  exclusiveMaximum:
-                                    type: boolean
-                                  exclusiveMinimum:
-                                    type: boolean
-                                  format:
-                                    description: "format is an OpenAPI v3 format string.
-                                      Unknown formats are ignored. The following formats
-                                      are validated: \n - bsonobjectid: a bson object
-                                      ID, i.e. a 24 characters hex string - uri: an
-                                      URI as parsed by Golang net/url.ParseRequestURI
-                                      - email: an email address as parsed by Golang
-                                      net/mail.ParseAddress - hostname: a valid representation
-                                      for an Internet host name, as defined by RFC
-                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
-                                      IP as parsed by Golang net.ParseIP - ipv6: an
-                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
-                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
-                                      a MAC address as parsed by Golang net.ParseMAC
-                                      - uuid: an UUID that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid3: an UUID3 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
-                                      - uuid4: an UUID4 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - uuid5: an UUID5 that allows uppercase defined
-                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
-                                      - isbn: an ISBN10 or ISBN13 number string like
-                                      \"0321751043\" or \"978-0321751041\" - isbn10:
-                                      an ISBN10 number string like \"0321751043\"
-                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
-                                      - creditcard: a credit card number defined by
-                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
-                                      with any non digit characters mixed in - ssn:
-                                      a U.S. social security number following the
-                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
-                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
-                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
-                                      - rgbcolor: an RGB color code like rgb like
-                                      \"rgb(255,255,2559\" - byte: base64 encoded
-                                      binary data - password: any kind of string -
-                                      date: a date string like \"2006-01-02\" as defined
-                                      by full-date in RFC3339 - duration: a duration
-                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
-                                      or compatible with Scala duration format - datetime:
-                                      a date time string like \"2014-12-15T19:30:20.000Z\"
-                                      as defined by date-time in RFC3339."
-                                    type: string
-                                  id:
-                                    type: string
-                                  maxItems:
-                                    format: int64
-                                    type: integer
-                                  maxLength:
-                                    format: int64
-                                    type: integer
-                                  maxProperties:
-                                    format: int64
-                                    type: integer
-                                  maximum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  minItems:
-                                    format: int64
-                                    type: integer
-                                  minLength:
-                                    format: int64
-                                    type: integer
-                                  minProperties:
-                                    format: int64
-                                    type: integer
-                                  minimum:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  multipleOf:
-                                    description: A Number represents a JSON number
-                                      literal.
-                                    type: string
-                                  nullable:
-                                    type: boolean
-                                  pattern:
-                                    type: string
-                                  title:
-                                    type: string
-                                  type:
+                                  additionalProperties:
+                                    properties:
+                                      default:
+                                        description: default is a default value for
+                                          undefined object fields.
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      description:
+                                        type: string
+                                      enum:
+                                        items:
+                                          description: 'JSON represents any valid
+                                            JSON value. These types are supported:
+                                            bool, int64, float64, string, []interface{},
+                                            map[string]interface{} and nil.'
+                                          x-kubernetes-preserve-unknown-fields: true
+                                        type: array
+                                      example:
+                                        description: 'JSON represents any valid JSON
+                                          value. These types are supported: bool,
+                                          int64, float64, string, []interface{}, map[string]interface{}
+                                          and nil.'
+                                        x-kubernetes-preserve-unknown-fields: true
+                                      exclusiveMaximum:
+                                        type: boolean
+                                      exclusiveMinimum:
+                                        type: boolean
+                                      format:
+                                        description: "format is an OpenAPI v3 format
+                                          string. Unknown formats are ignored. The
+                                          following formats are validated: \n - bsonobjectid:
+                                          a bson object ID, i.e. a 24 characters hex
+                                          string - uri: an URI as parsed by Golang
+                                          net/url.ParseRequestURI - email: an email
+                                          address as parsed by Golang net/mail.ParseAddress
+                                          - hostname: a valid representation for an
+                                          Internet host name, as defined by RFC 1034,
+                                          section 3.1 [RFC1034]. - ipv4: an IPv4 IP
+                                          as parsed by Golang net.ParseIP - ipv6:
+                                          an IPv6 IP as parsed by Golang net.ParseIP
+                                          - cidr: a CIDR as parsed by Golang net.ParseCIDR
+                                          - mac: a MAC address as parsed by Golang
+                                          net.ParseMAC - uuid: an UUID that allows
+                                          uppercase defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid3: an UUID3 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                          - uuid4: an UUID4 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - uuid5: an UUID5 that allows uppercase
+                                          defined by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                          - isbn: an ISBN10 or ISBN13 number string
+                                          like \"0321751043\" or \"978-0321751041\"
+                                          - isbn10: an ISBN10 number string like \"0321751043\"
+                                          - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                          - creditcard: a credit card number defined
+                                          by the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                          with any non digit characters mixed in -
+                                          ssn: a U.S. social security number following
+                                          the regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$
+                                          - hexcolor: an hexadecimal color code like
+                                          \"#FFFFFF: following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                          - rgbcolor: an RGB color code like rgb like
+                                          \"rgb(255,255,2559\" - byte: base64 encoded
+                                          binary data - password: any kind of string
+                                          - date: a date string like \"2006-01-02\"
+                                          as defined by full-date in RFC3339 - duration:
+                                          a duration string like \"22 ns\" as parsed
+                                          by Golang time.ParseDuration or compatible
+                                          with Scala duration format - datetime: a
+                                          date time string like \"2014-12-15T19:30:20.000Z\"
+                                          as defined by date-time in RFC3339."
+                                        type: string
+                                      id:
+                                        type: string
+                                      maxItems:
+                                        format: int64
+                                        type: integer
+                                      maxLength:
+                                        format: int64
+                                        type: integer
+                                      maxProperties:
+                                        format: int64
+                                        type: integer
+                                      maximum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      minItems:
+                                        format: int64
+                                        type: integer
+                                      minLength:
+                                        format: int64
+                                        type: integer
+                                      minProperties:
+                                        format: int64
+                                        type: integer
+                                      minimum:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      multipleOf:
+                                        description: A Number represents a JSON number
+                                          literal.
+                                        type: string
+                                      nullable:
+                                        type: boolean
+                                      pattern:
+                                        type: string
+                                      title:
+                                        type: string
+                                      type:
+                                        type: string
+                                      uniqueItems:
+                                        type: boolean
+                                      x-descriptors:
+                                        description: The list of descriptors that
+                                          determine which UI components to use on
+                                          different views
+                                        items:
+                                          type: string
+                                        type: array
+                                    type: object
+                                  type: object
+                                required:
+                                  items:
                                     type: string
-                                  uniqueItems:
-                                    type: boolean
-                                  x-descriptors:
-                                    description: The list of descriptors that determine
-                                      which UI components to use on different views
-                                    items:
-                                      type: string
-                                    type: array
-                                type: object
+                                  type: array
+                                title:
+                                  type: string
+                                type:
+                                  type: string
                               type: object
-                            required:
-                              items:
-                                type: string
-                              type: array
-                            title:
-                              type: string
-                            type:
-                              type: string
                           type: object
-                      type: object
-                    description: Types defines the schema of the data produced/consumed
-                      by the endpoint
+                        description: Types defines the schema of the data produced/consumed
+                          by the endpoint
+                        type: object
+                      uri:
+                        description: URI can alternatively be used to specify the
+                          (Camel) endpoint explicitly
+                        type: string
                     type: object
-                  uri:
-                    description: URI can alternatively be used to specify the (Camel)
-                      endpoint explicitly
+                  type:
                     type: string
                 type: object
               integration:
@@ -298,6 +312,19 @@ spec:
                     items:
                       type: string
                     type: array
+                  errorHandler:
+                    description: ErrorHandlerSpec respresents an integration error
+                      handler to be used as default at runtime
+                    properties:
+                      configuration:
+                        description: ErrorHandlerConfiguration --
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      type:
+                        type: string
+                      uri:
+                        type: string
+                    type: object
                   flows:
                     items:
                       description: Flow is an unstructured object representing a Camel

[camel-k] 22/30: refactor(trait): error handler language to yaml

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit d1a72fd77246b93c13a834db5e65bbcc8eb4112e
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 10:44:19 2021 +0200

    refactor(trait): error handler language to yaml
---
 .../kamelet-binding-error-handler.yaml             | 11 +++-
 pkg/trait/error_handler.go                         | 61 ++++++++--------------
 2 files changed, 31 insertions(+), 41 deletions(-)

diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
index 5f62adc..6c44ca7 100644
--- a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -30,7 +30,16 @@ spec:
       kind: Kamelet
       apiVersion: camel.apache.org/v1alpha1
       name: log-sink
-  errorHandler:
+  errorHandler:   
+#    log:
+#      parameters:
+#        maximumRedeliveries: 3
+#        redeliveryDelay: 2000      
+#    ref: "something"
+#    bean:
+#      type: "org.apache.camel.builder.DeadLetterChannelBuilder"
+#      parameters:
+#        deadLetterUri: log:error
     dead-letter-channel:
       endpoint:
         ref:
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index fbd757f..dd6e218 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -18,10 +18,9 @@ limitations under the License.
 package trait
 
 import (
-	"fmt"
-
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"gopkg.in/yaml.v2"
 )
 
 // The error-handler is a platform trait used to inject Error Handler source into the integration runtime.
@@ -29,6 +28,8 @@ import (
 // +camel-k:trait=error-handler
 type errorHandlerTrait struct {
 	BaseTrait `property:",squash"`
+	// The error handler ref name found in application properties
+	ErrorHandlerRef string `property:",omitempty"`
 }
 
 func newErrorHandlerTrait() Trait {
@@ -51,57 +52,37 @@ func (t *errorHandlerTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	return e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName) != "", nil
+	t.ErrorHandlerRef = e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName)
+
+	return t.ErrorHandlerRef != "", nil
 }
 
 func (t *errorHandlerTrait) Apply(e *Environment) error {
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-		err := addErrorHandlerAsSource(e)
-		if err != nil {
-			return err
-		}
+		return t.addErrorHandlerAsSource(e)
 	}
 	return nil
 }
 
-func addErrorHandlerAsSource(e *Environment) error {
-	errorHandlerRefName := e.Integration.Spec.GetConfigurationProperty(v1alpha1.ErrorHandlerRefName)
-	// TODO change to yaml flow when we fix https://issues.apache.org/jira/browse/CAMEL-16486
+func (t *errorHandlerTrait) addErrorHandlerAsSource(e *Environment) error {
+	flowErrorHandler := map[string]interface{}{
+		"error-handler": map[string]string{
+			"ref": t.ErrorHandlerRef,
+		},
+	}
+	encodedFlowErrorHandler, err := yaml.Marshal([]map[string]interface{}{flowErrorHandler})
+	if err != nil {
+		return err
+	}
 	errorHandlerSource := v1.SourceSpec{
 		DataSpec: v1.DataSpec{
-			Name: "ErrorHandlerSource.java",
-			Content: fmt.Sprintf(`
-			import org.apache.camel.builder.RouteBuilder;
-			public class ErrorHandlerSource extends RouteBuilder {
-			@Override
-			public void configure() throws Exception {
-				errorHandler("%s");
-			  }
-			}
-			`, errorHandlerRefName),
+			Name:    "camel-k-embedded-error-handler.yaml",
+			Content: string(encodedFlowErrorHandler),
 		},
-		Language: v1.LanguageJavaSource,
+		Language: v1.LanguageYaml,
 		Type:     v1.SourceTypeErrorHandler,
 	}
-	/*
-		flowErrorHandler := map[string]interface{}{
-			"error-handler": map[string]string{
-				"ref": errorHandlerRefName,
-			},
-		}
-		encodedFlowErrorHandler, err := yaml.Marshal(flowErrorHandler)
-		if err != nil {
-			return err
-		}
-		errorHandlerSource := v1.SourceSpec{
-			DataSpec: v1.DataSpec{
-				Name:    "ErrorHandlerSource.yaml",
-				Content: string(encodedFlowErrorHandler),
-			},
-			Language: v1.LanguageYaml,
-			Type:     v1.SourceTypeErrorHandler,
-		}
-	*/
+
 	e.Integration.Status.AddOrReplaceGeneratedSources(errorHandlerSource)
 
 	return nil

[camel-k] 05/30: feat(crd): kameletbinding error handler

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 619806dccddc3311554117e731f8ddba373631ef
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 13 14:21:16 2021 +0200

    feat(crd): kameletbinding error handler
---
 .../bases/camel.apache.org_kameletbindings.yaml    | 214 +++++++++++++++++++++
 .../1.4.0/camel.apache.org_kameletbindings.yaml    | 214 +++++++++++++++++++++
 helm/camel-k/crds/crd-kamelet-binding.yaml         | 214 +++++++++++++++++++++
 3 files changed, 642 insertions(+)

diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index c9a8b87..7c43c55 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -63,6 +63,220 @@ spec:
           spec:
             description: KameletBindingSpec --
             properties:
+              errorHandler:
+                description: ErrorHandler is an optional handler called upon an error
+                  occuring in the integration
+                properties:
+                  properties:
+                    description: Properties are a key value representation of endpoint
+                      properties
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  ref:
+                    description: Ref can be used to declare a Kubernetes resource
+                      as source/sink endpoint
+                    properties:
+                      apiVersion:
+                        description: API version of the referent.
+                        type: string
+                      fieldPath:
+                        description: 'If referring to a piece of an object instead
+                          of an entire object, this string should contain a valid
+                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                          For example, if the object reference is to a container within
+                          a pod, this would take on a value like: "spec.containers{name}"
+                          (where "name" refers to the name of the container that triggered
+                          the event) or if no container name is specified "spec.containers[2]"
+                          (container with index 2 in this pod). This syntax is chosen
+                          only to have some well-defined way of referencing a part
+                          of an object. TODO: this design is not final and this field
+                          is subject to change in the future.'
+                        type: string
+                      kind:
+                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                        type: string
+                      name:
+                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                        type: string
+                      namespace:
+                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                        type: string
+                      resourceVersion:
+                        description: 'Specific resourceVersion to which this reference
+                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                        type: string
+                      uid:
+                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                        type: string
+                    type: object
+                  types:
+                    additionalProperties:
+                      properties:
+                        mediaType:
+                          type: string
+                        schema:
+                          description: JSONSchemaProps is a JSON-Schema following
+                            Specification Draft 4 (http://json-schema.org/).
+                          properties:
+                            $schema:
+                              description: JSONSchemaURL represents a schema url.
+                              type: string
+                            description:
+                              type: string
+                            example:
+                              description: 'JSON represents any valid JSON value.
+                                These types are supported: bool, int64, float64, string,
+                                []interface{}, map[string]interface{} and nil.'
+                              x-kubernetes-preserve-unknown-fields: true
+                            externalDocs:
+                              description: ExternalDocumentation allows referencing
+                                an external resource for extended documentation.
+                              properties:
+                                description:
+                                  type: string
+                                url:
+                                  type: string
+                              type: object
+                            id:
+                              type: string
+                            properties:
+                              additionalProperties:
+                                properties:
+                                  default:
+                                    description: default is a default value for undefined
+                                      object fields.
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  description:
+                                    type: string
+                                  enum:
+                                    items:
+                                      description: 'JSON represents any valid JSON
+                                        value. These types are supported: bool, int64,
+                                        float64, string, []interface{}, map[string]interface{}
+                                        and nil.'
+                                      x-kubernetes-preserve-unknown-fields: true
+                                    type: array
+                                  example:
+                                    description: 'JSON represents any valid JSON value.
+                                      These types are supported: bool, int64, float64,
+                                      string, []interface{}, map[string]interface{}
+                                      and nil.'
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  exclusiveMaximum:
+                                    type: boolean
+                                  exclusiveMinimum:
+                                    type: boolean
+                                  format:
+                                    description: "format is an OpenAPI v3 format string.
+                                      Unknown formats are ignored. The following formats
+                                      are validated: \n - bsonobjectid: a bson object
+                                      ID, i.e. a 24 characters hex string - uri: an
+                                      URI as parsed by Golang net/url.ParseRequestURI
+                                      - email: an email address as parsed by Golang
+                                      net/mail.ParseAddress - hostname: a valid representation
+                                      for an Internet host name, as defined by RFC
+                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
+                                      IP as parsed by Golang net.ParseIP - ipv6: an
+                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
+                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
+                                      a MAC address as parsed by Golang net.ParseMAC
+                                      - uuid: an UUID that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid3: an UUID3 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid4: an UUID4 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - uuid5: an UUID5 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - isbn: an ISBN10 or ISBN13 number string like
+                                      \"0321751043\" or \"978-0321751041\" - isbn10:
+                                      an ISBN10 number string like \"0321751043\"
+                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                      - creditcard: a credit card number defined by
+                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                      with any non digit characters mixed in - ssn:
+                                      a U.S. social security number following the
+                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
+                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
+                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                      - rgbcolor: an RGB color code like rgb like
+                                      \"rgb(255,255,2559\" - byte: base64 encoded
+                                      binary data - password: any kind of string -
+                                      date: a date string like \"2006-01-02\" as defined
+                                      by full-date in RFC3339 - duration: a duration
+                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
+                                      or compatible with Scala duration format - datetime:
+                                      a date time string like \"2014-12-15T19:30:20.000Z\"
+                                      as defined by date-time in RFC3339."
+                                    type: string
+                                  id:
+                                    type: string
+                                  maxItems:
+                                    format: int64
+                                    type: integer
+                                  maxLength:
+                                    format: int64
+                                    type: integer
+                                  maxProperties:
+                                    format: int64
+                                    type: integer
+                                  maximum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  minItems:
+                                    format: int64
+                                    type: integer
+                                  minLength:
+                                    format: int64
+                                    type: integer
+                                  minProperties:
+                                    format: int64
+                                    type: integer
+                                  minimum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  multipleOf:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  nullable:
+                                    type: boolean
+                                  pattern:
+                                    type: string
+                                  title:
+                                    type: string
+                                  type:
+                                    type: string
+                                  uniqueItems:
+                                    type: boolean
+                                  x-descriptors:
+                                    description: The list of descriptors that determine
+                                      which UI components to use on different views
+                                    items:
+                                      type: string
+                                    type: array
+                                type: object
+                              type: object
+                            required:
+                              items:
+                                type: string
+                              type: array
+                            title:
+                              type: string
+                            type:
+                              type: string
+                          type: object
+                      type: object
+                    description: Types defines the schema of the data produced/consumed
+                      by the endpoint
+                    type: object
+                  uri:
+                    description: URI can alternatively be used to specify the (Camel)
+                      endpoint explicitly
+                    type: string
+                type: object
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
diff --git a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
index c9a8b87..7c43c55 100644
--- a/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
+++ b/deploy/olm-catalog/camel-k-dev/1.4.0/camel.apache.org_kameletbindings.yaml
@@ -63,6 +63,220 @@ spec:
           spec:
             description: KameletBindingSpec --
             properties:
+              errorHandler:
+                description: ErrorHandler is an optional handler called upon an error
+                  occuring in the integration
+                properties:
+                  properties:
+                    description: Properties are a key value representation of endpoint
+                      properties
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  ref:
+                    description: Ref can be used to declare a Kubernetes resource
+                      as source/sink endpoint
+                    properties:
+                      apiVersion:
+                        description: API version of the referent.
+                        type: string
+                      fieldPath:
+                        description: 'If referring to a piece of an object instead
+                          of an entire object, this string should contain a valid
+                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                          For example, if the object reference is to a container within
+                          a pod, this would take on a value like: "spec.containers{name}"
+                          (where "name" refers to the name of the container that triggered
+                          the event) or if no container name is specified "spec.containers[2]"
+                          (container with index 2 in this pod). This syntax is chosen
+                          only to have some well-defined way of referencing a part
+                          of an object. TODO: this design is not final and this field
+                          is subject to change in the future.'
+                        type: string
+                      kind:
+                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                        type: string
+                      name:
+                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                        type: string
+                      namespace:
+                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                        type: string
+                      resourceVersion:
+                        description: 'Specific resourceVersion to which this reference
+                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                        type: string
+                      uid:
+                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                        type: string
+                    type: object
+                  types:
+                    additionalProperties:
+                      properties:
+                        mediaType:
+                          type: string
+                        schema:
+                          description: JSONSchemaProps is a JSON-Schema following
+                            Specification Draft 4 (http://json-schema.org/).
+                          properties:
+                            $schema:
+                              description: JSONSchemaURL represents a schema url.
+                              type: string
+                            description:
+                              type: string
+                            example:
+                              description: 'JSON represents any valid JSON value.
+                                These types are supported: bool, int64, float64, string,
+                                []interface{}, map[string]interface{} and nil.'
+                              x-kubernetes-preserve-unknown-fields: true
+                            externalDocs:
+                              description: ExternalDocumentation allows referencing
+                                an external resource for extended documentation.
+                              properties:
+                                description:
+                                  type: string
+                                url:
+                                  type: string
+                              type: object
+                            id:
+                              type: string
+                            properties:
+                              additionalProperties:
+                                properties:
+                                  default:
+                                    description: default is a default value for undefined
+                                      object fields.
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  description:
+                                    type: string
+                                  enum:
+                                    items:
+                                      description: 'JSON represents any valid JSON
+                                        value. These types are supported: bool, int64,
+                                        float64, string, []interface{}, map[string]interface{}
+                                        and nil.'
+                                      x-kubernetes-preserve-unknown-fields: true
+                                    type: array
+                                  example:
+                                    description: 'JSON represents any valid JSON value.
+                                      These types are supported: bool, int64, float64,
+                                      string, []interface{}, map[string]interface{}
+                                      and nil.'
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  exclusiveMaximum:
+                                    type: boolean
+                                  exclusiveMinimum:
+                                    type: boolean
+                                  format:
+                                    description: "format is an OpenAPI v3 format string.
+                                      Unknown formats are ignored. The following formats
+                                      are validated: \n - bsonobjectid: a bson object
+                                      ID, i.e. a 24 characters hex string - uri: an
+                                      URI as parsed by Golang net/url.ParseRequestURI
+                                      - email: an email address as parsed by Golang
+                                      net/mail.ParseAddress - hostname: a valid representation
+                                      for an Internet host name, as defined by RFC
+                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
+                                      IP as parsed by Golang net.ParseIP - ipv6: an
+                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
+                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
+                                      a MAC address as parsed by Golang net.ParseMAC
+                                      - uuid: an UUID that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid3: an UUID3 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid4: an UUID4 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - uuid5: an UUID5 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - isbn: an ISBN10 or ISBN13 number string like
+                                      \"0321751043\" or \"978-0321751041\" - isbn10:
+                                      an ISBN10 number string like \"0321751043\"
+                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                      - creditcard: a credit card number defined by
+                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                      with any non digit characters mixed in - ssn:
+                                      a U.S. social security number following the
+                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
+                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
+                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                      - rgbcolor: an RGB color code like rgb like
+                                      \"rgb(255,255,2559\" - byte: base64 encoded
+                                      binary data - password: any kind of string -
+                                      date: a date string like \"2006-01-02\" as defined
+                                      by full-date in RFC3339 - duration: a duration
+                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
+                                      or compatible with Scala duration format - datetime:
+                                      a date time string like \"2014-12-15T19:30:20.000Z\"
+                                      as defined by date-time in RFC3339."
+                                    type: string
+                                  id:
+                                    type: string
+                                  maxItems:
+                                    format: int64
+                                    type: integer
+                                  maxLength:
+                                    format: int64
+                                    type: integer
+                                  maxProperties:
+                                    format: int64
+                                    type: integer
+                                  maximum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  minItems:
+                                    format: int64
+                                    type: integer
+                                  minLength:
+                                    format: int64
+                                    type: integer
+                                  minProperties:
+                                    format: int64
+                                    type: integer
+                                  minimum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  multipleOf:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  nullable:
+                                    type: boolean
+                                  pattern:
+                                    type: string
+                                  title:
+                                    type: string
+                                  type:
+                                    type: string
+                                  uniqueItems:
+                                    type: boolean
+                                  x-descriptors:
+                                    description: The list of descriptors that determine
+                                      which UI components to use on different views
+                                    items:
+                                      type: string
+                                    type: array
+                                type: object
+                              type: object
+                            required:
+                              items:
+                                type: string
+                              type: array
+                            title:
+                              type: string
+                            type:
+                              type: string
+                          type: object
+                      type: object
+                    description: Types defines the schema of the data produced/consumed
+                      by the endpoint
+                    type: object
+                  uri:
+                    description: URI can alternatively be used to specify the (Camel)
+                      endpoint explicitly
+                    type: string
+                type: object
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index c9a8b87..7c43c55 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -63,6 +63,220 @@ spec:
           spec:
             description: KameletBindingSpec --
             properties:
+              errorHandler:
+                description: ErrorHandler is an optional handler called upon an error
+                  occuring in the integration
+                properties:
+                  properties:
+                    description: Properties are a key value representation of endpoint
+                      properties
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                  ref:
+                    description: Ref can be used to declare a Kubernetes resource
+                      as source/sink endpoint
+                    properties:
+                      apiVersion:
+                        description: API version of the referent.
+                        type: string
+                      fieldPath:
+                        description: 'If referring to a piece of an object instead
+                          of an entire object, this string should contain a valid
+                          JSON/Go field access statement, such as desiredState.manifest.containers[2].
+                          For example, if the object reference is to a container within
+                          a pod, this would take on a value like: "spec.containers{name}"
+                          (where "name" refers to the name of the container that triggered
+                          the event) or if no container name is specified "spec.containers[2]"
+                          (container with index 2 in this pod). This syntax is chosen
+                          only to have some well-defined way of referencing a part
+                          of an object. TODO: this design is not final and this field
+                          is subject to change in the future.'
+                        type: string
+                      kind:
+                        description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                        type: string
+                      name:
+                        description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                        type: string
+                      namespace:
+                        description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                        type: string
+                      resourceVersion:
+                        description: 'Specific resourceVersion to which this reference
+                          is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
+                        type: string
+                      uid:
+                        description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
+                        type: string
+                    type: object
+                  types:
+                    additionalProperties:
+                      properties:
+                        mediaType:
+                          type: string
+                        schema:
+                          description: JSONSchemaProps is a JSON-Schema following
+                            Specification Draft 4 (http://json-schema.org/).
+                          properties:
+                            $schema:
+                              description: JSONSchemaURL represents a schema url.
+                              type: string
+                            description:
+                              type: string
+                            example:
+                              description: 'JSON represents any valid JSON value.
+                                These types are supported: bool, int64, float64, string,
+                                []interface{}, map[string]interface{} and nil.'
+                              x-kubernetes-preserve-unknown-fields: true
+                            externalDocs:
+                              description: ExternalDocumentation allows referencing
+                                an external resource for extended documentation.
+                              properties:
+                                description:
+                                  type: string
+                                url:
+                                  type: string
+                              type: object
+                            id:
+                              type: string
+                            properties:
+                              additionalProperties:
+                                properties:
+                                  default:
+                                    description: default is a default value for undefined
+                                      object fields.
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  description:
+                                    type: string
+                                  enum:
+                                    items:
+                                      description: 'JSON represents any valid JSON
+                                        value. These types are supported: bool, int64,
+                                        float64, string, []interface{}, map[string]interface{}
+                                        and nil.'
+                                      x-kubernetes-preserve-unknown-fields: true
+                                    type: array
+                                  example:
+                                    description: 'JSON represents any valid JSON value.
+                                      These types are supported: bool, int64, float64,
+                                      string, []interface{}, map[string]interface{}
+                                      and nil.'
+                                    x-kubernetes-preserve-unknown-fields: true
+                                  exclusiveMaximum:
+                                    type: boolean
+                                  exclusiveMinimum:
+                                    type: boolean
+                                  format:
+                                    description: "format is an OpenAPI v3 format string.
+                                      Unknown formats are ignored. The following formats
+                                      are validated: \n - bsonobjectid: a bson object
+                                      ID, i.e. a 24 characters hex string - uri: an
+                                      URI as parsed by Golang net/url.ParseRequestURI
+                                      - email: an email address as parsed by Golang
+                                      net/mail.ParseAddress - hostname: a valid representation
+                                      for an Internet host name, as defined by RFC
+                                      1034, section 3.1 [RFC1034]. - ipv4: an IPv4
+                                      IP as parsed by Golang net.ParseIP - ipv6: an
+                                      IPv6 IP as parsed by Golang net.ParseIP - cidr:
+                                      a CIDR as parsed by Golang net.ParseCIDR - mac:
+                                      a MAC address as parsed by Golang net.ParseMAC
+                                      - uuid: an UUID that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid3: an UUID3 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?3[0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12}$
+                                      - uuid4: an UUID4 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - uuid5: an UUID5 that allows uppercase defined
+                                      by the regex (?i)^[0-9a-f]{8}-?[0-9a-f]{4}-?5[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$
+                                      - isbn: an ISBN10 or ISBN13 number string like
+                                      \"0321751043\" or \"978-0321751041\" - isbn10:
+                                      an ISBN10 number string like \"0321751043\"
+                                      - isbn13: an ISBN13 number string like \"978-0321751041\"
+                                      - creditcard: a credit card number defined by
+                                      the regex ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\\\d{3})\\\\d{11})$
+                                      with any non digit characters mixed in - ssn:
+                                      a U.S. social security number following the
+                                      regex ^\\\\d{3}[- ]?\\\\d{2}[- ]?\\\\d{4}$ -
+                                      hexcolor: an hexadecimal color code like \"#FFFFFF:
+                                      following the regex ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
+                                      - rgbcolor: an RGB color code like rgb like
+                                      \"rgb(255,255,2559\" - byte: base64 encoded
+                                      binary data - password: any kind of string -
+                                      date: a date string like \"2006-01-02\" as defined
+                                      by full-date in RFC3339 - duration: a duration
+                                      string like \"22 ns\" as parsed by Golang time.ParseDuration
+                                      or compatible with Scala duration format - datetime:
+                                      a date time string like \"2014-12-15T19:30:20.000Z\"
+                                      as defined by date-time in RFC3339."
+                                    type: string
+                                  id:
+                                    type: string
+                                  maxItems:
+                                    format: int64
+                                    type: integer
+                                  maxLength:
+                                    format: int64
+                                    type: integer
+                                  maxProperties:
+                                    format: int64
+                                    type: integer
+                                  maximum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  minItems:
+                                    format: int64
+                                    type: integer
+                                  minLength:
+                                    format: int64
+                                    type: integer
+                                  minProperties:
+                                    format: int64
+                                    type: integer
+                                  minimum:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  multipleOf:
+                                    description: A Number represents a JSON number
+                                      literal.
+                                    type: string
+                                  nullable:
+                                    type: boolean
+                                  pattern:
+                                    type: string
+                                  title:
+                                    type: string
+                                  type:
+                                    type: string
+                                  uniqueItems:
+                                    type: boolean
+                                  x-descriptors:
+                                    description: The list of descriptors that determine
+                                      which UI components to use on different views
+                                    items:
+                                      type: string
+                                    type: array
+                                type: object
+                              type: object
+                            required:
+                              items:
+                                type: string
+                              type: array
+                            title:
+                              type: string
+                            type:
+                              type: string
+                          type: object
+                      type: object
+                    description: Types defines the schema of the data produced/consumed
+                      by the endpoint
+                    type: object
+                  uri:
+                    description: URI can alternatively be used to specify the (Camel)
+                      endpoint explicitly
+                    type: string
+                type: object
               integration:
                 description: Integration is an optional integration used to specify
                   custom parameters

[camel-k] 04/30: feat(kamelets): error handling kamelets binding support

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 1849ca5223a865eb1cf3b7acab7a78c3540f8ea0
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 13 14:20:45 2021 +0200

    feat(kamelets): error handling kamelets binding support
    
    Mark error-handler kamelet source with errorHandler source type
---
 pkg/apis/camel/v1/common_types.go       |   5 +-
 pkg/controller/kameletbinding/common.go |  52 ++++++++--------
 pkg/trait/kamelets.go                   | 106 ++++++++++++++++++++++++--------
 pkg/util/source/inspector_yaml.go       |   4 --
 pkg/util/source/types.go                |   2 -
 5 files changed, 109 insertions(+), 60 deletions(-)

diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go
index a94d604..e5b327b 100644
--- a/pkg/apis/camel/v1/common_types.go
+++ b/pkg/apis/camel/v1/common_types.go
@@ -206,8 +206,9 @@ type SourceSpec struct {
 type SourceType string
 
 const (
-	SourceTypeDefault  SourceType = ""
-	SourceTypeTemplate SourceType = "template"
+	SourceTypeDefault      SourceType = ""
+	SourceTypeTemplate     SourceType = "template"
+	SourceTypeErrorHandler SourceType = "errorHandler"
 )
 
 // DataSpec --
diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 32d7182..fdeab95 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -22,6 +22,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"sort"
+	"strings"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -79,12 +80,17 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
-	var onError *bindings.Binding
+	var errorHandler *bindings.Binding
 	if kameletbinding.Spec.ErrorHandler.Ref != nil || kameletbinding.Spec.ErrorHandler.URI != nil {
-		onError, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
+		errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not determine error handler URI")
 		}
+
+		err = setErrorHandlerKamelet(errorHandler, kameletbinding.Spec.ErrorHandler)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not set error handler")
+		}
 	}
 
 	steps := make([]*bindings.Binding, 0, len(kameletbinding.Spec.Steps))
@@ -104,8 +110,8 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	allBindings = append(allBindings, from)
 	allBindings = append(allBindings, steps...)
 	allBindings = append(allBindings, to)
-	if onError != nil {
-		allBindings = append(allBindings, onError)
+	if errorHandler != nil {
+		allBindings = append(allBindings, errorHandler)
 	}
 
 	propList := make([]string, 0)
@@ -139,27 +145,6 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		"to": to.URI,
 	})
 
-	// Append Error Handler flow, if it exists
-	if onError != nil {
-		flowErrorHandler := map[string]interface{}{
-			"error-handler": map[string]interface{}{
-				"dead-letter-channel": map[string]interface{}{
-					"dead-letter-uri":                  onError.URI,
-					"dead-letter-handle-new-exception": true,
-					"async-delayed-redelivery":         false,
-					"use-original-message":             true,
-				},
-			},
-		}
-		encodedErrorHandler, err := json.Marshal(flowErrorHandler)
-
-		if err != nil {
-			return nil, err
-		}
-		it.Spec.Flows = append(it.Spec.Flows, v1.Flow{RawMessage: encodedErrorHandler})
-	}
-
-	// Append From flow: it must exist
 	flowFrom := map[string]interface{}{
 		"from": map[string]interface{}{
 			"uri":   from.URI,
@@ -175,6 +160,23 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	return &it, nil
 }
 
+func setErrorHandlerKamelet(errorHandler *bindings.Binding, kameletSpec v1alpha1.Endpoint) error {
+	if errorHandler.ApplicationProperties == nil {
+		errorHandler.ApplicationProperties = make(map[string]string)
+	}
+	if kameletSpec.URI != nil {
+		if !strings.HasPrefix(*kameletSpec.URI, "kamelet") {
+			return fmt.Errorf("Kamelet Binding only supports kamelet as error handler, provided: %s", *kameletSpec.URI)
+		}
+
+		errorHandler.ApplicationProperties["camel.k.default-error-handler"] = *kameletSpec.URI
+		return nil
+	}
+
+	errorHandler.ApplicationProperties["camel.k.default-error-handler"] = kameletSpec.Ref.Name
+	return nil
+}
+
 func determineProfile(ctx context.Context, c client.Client, binding *v1alpha1.KameletBinding) (v1.TraitProfile, error) {
 	if binding.Spec.Integration != nil && binding.Spec.Integration.Profile != "" {
 		return binding.Spec.Integration.Profile, nil
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 9d55b19..053678d 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -47,6 +47,8 @@ type kameletsTrait struct {
 	Auto *bool `property:"auto"`
 	// Comma separated list of Kamelet names to load into the current integration
 	List string `property:"list"`
+	// Kamelet name used as error handler
+	ErrorHandler string `property:"error-handler"`
 }
 
 type configurationKey struct {
@@ -103,16 +105,37 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 			metadata.Each(e.CamelCatalog, sources, func(_ int, meta metadata.IntegrationMetadata) bool {
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.FromURIs))
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ToURIs))
-				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ErrorHandlerURIs))
 				return true
 			})
 			sort.Strings(kamelets)
 			t.List = strings.Join(kamelets, ",")
 		}
+		if t.ErrorHandler == "" {
+			t.ErrorHandler = maybeKameletAsDefaultErrorHandler(e.Integration.Configurations())
+		}
+	}
+
+	return t.declareKamelets(), nil
+}
 
+func maybeKameletAsDefaultErrorHandler(properties []v1.ConfigurationSpec) string {
+	for _, property := range properties {
+		if strings.HasPrefix(property.Value, "camel.k.default-error-handler=") {
+			split := strings.Split(property.Value, "=")
+			if len(split) > 0 {
+				if strings.HasPrefix(split[1], "kamelet:") {
+					return extractKamelet(split[1])
+				}
+				return split[1]
+			}
+		}
 	}
 
-	return len(t.getKameletKeys()) > 0, nil
+	return ""
+}
+
+func (t *kameletsTrait) declareKamelets() bool {
+	return len(t.getKameletKeys()) > 0 || t.ErrorHandler != ""
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
@@ -133,44 +156,62 @@ func (t *kameletsTrait) Apply(e *Environment) error {
 }
 
 func (t *kameletsTrait) addKamelets(e *Environment) error {
-	kameletKeys := t.getKameletKeys()
-	if len(kameletKeys) > 0 {
+	if t.declareKamelets() {
 		repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
 		if err != nil {
 			return err
 		}
+
+		// Declared kamelets
 		for _, k := range t.getKameletKeys() {
-			kamelet, err := repo.Get(e.C, k)
+			err := initializeKamelet(repo, e, k, t, v1.SourceTypeTemplate)
 			if err != nil {
 				return err
 			}
-			if kamelet == nil {
-				return fmt.Errorf("kamelet %s not found in any of the defined repositories: %s", k, repo.String())
-			}
-
-			// Initialize remote kamelets
-			kamelet, err = kameletutils.Initialize(kamelet)
+		}
+		if t.ErrorHandler != "" {
+			// Possible error handler
+			err = initializeKamelet(repo, e, t.ErrorHandler, t, v1.SourceTypeErrorHandler)
 			if err != nil {
 				return err
 			}
-
-			if kamelet.Status.Phase != v1alpha1.KameletPhaseReady {
-				return fmt.Errorf("kamelet %q is not %s: %s", k, v1alpha1.KameletPhaseReady, kamelet.Status.Phase)
-			}
-
-			if err := t.addKameletAsSource(e, kamelet); err != nil {
-				return err
-			}
-
-			// Adding dependencies from Kamelets
-			util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, kamelet.Spec.Dependencies)
 		}
+
 		// resort dependencies
 		sort.Strings(e.Integration.Status.Dependencies)
 	}
 	return nil
 }
 
+func initializeKamelet(repo repository.KameletRepository, e *Environment, k string, t *kameletsTrait, sourceType v1.SourceType) error {
+	kamelet, err := repo.Get(e.C, k)
+	if err != nil {
+		return err
+	}
+	if kamelet == nil {
+		return fmt.Errorf("kamelet %s not found in any of the defined repositories: %s", k, repo.String())
+	}
+
+	// Initialize remote kamelets
+	kamelet, err = kameletutils.Initialize(kamelet)
+	if err != nil {
+		return err
+	}
+
+	if kamelet.Status.Phase != v1alpha1.KameletPhaseReady {
+		return fmt.Errorf("kamelet %q is not %s: %s", k, v1alpha1.KameletPhaseReady, kamelet.Status.Phase)
+	}
+
+	if err := t.addKameletAsSource(e, kamelet, sourceType); err != nil {
+		return err
+	}
+
+	// Adding dependencies from Kamelets
+	util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, kamelet.Spec.Dependencies)
+
+	return nil
+}
+
 func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
 	if len(t.getKameletKeys()) > 0 {
 		repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
@@ -215,7 +256,7 @@ func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
 	return nil
 }
 
-func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet) error {
+func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet, sourceType v1.SourceType) error {
 	sources := make([]v1.SourceSpec, 0)
 
 	if kamelet.Spec.Flow != nil {
@@ -236,7 +277,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
 				Content: string(flowData),
 			},
 			Language:      v1.LanguageYaml,
-			Type:          v1.SourceTypeTemplate,
+			Type:          sourceType,
 			PropertyNames: propertyNames,
 		}
 		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
@@ -247,6 +288,9 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
 	}
 
 	for idx, s := range kamelet.Spec.Sources {
+		if sourceType == v1.SourceTypeErrorHandler {
+			s.Type = sourceType
+		}
 		intSource, err := integrationSourceFromKameletSource(e, kamelet, s, fmt.Sprintf("%s-kamelet-%s-%03d", e.Integration.Name, kamelet.Name, idx))
 		if err != nil {
 			return err
@@ -405,10 +449,18 @@ func integrationSourceFromKameletSource(e *Environment, kamelet *v1alpha1.Kamele
 
 func extractKamelets(uris []string) (kamelets []string) {
 	for _, uri := range uris {
-		matches := kameletNameRegexp.FindStringSubmatch(uri)
-		if len(matches) > 1 {
-			kamelets = append(kamelets, matches[1])
+		kamelet := extractKamelet(uri)
+		if kamelet != "" {
+			kamelets = append(kamelets, kamelet)
 		}
 	}
 	return
 }
+
+func extractKamelet(uri string) (kamelet string) {
+	matches := kameletNameRegexp.FindStringSubmatch(uri)
+	if len(matches) > 1 {
+		return matches[1]
+	}
+	return ""
+}
diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go
index 4c47dc2..1f96ae8 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -78,10 +78,6 @@ func (i YAMLInspector) parseStep(key string, content interface{}, meta *Metadata
 				}
 			}
 		}
-	case "error-handler":
-		deadLetterChannel := content.(map[interface{}]interface{})
-		deadLetterURI := deadLetterChannel["dead-letter-channel"].(map[interface{}]interface{})
-		meta.ErrorHandlerURIs = append(meta.ErrorHandlerURIs, deadLetterURI["dead-letter-uri"].(string))
 	}
 
 	var maybeURI string
diff --git a/pkg/util/source/types.go b/pkg/util/source/types.go
index 46074f8..f6f15e0 100644
--- a/pkg/util/source/types.go
+++ b/pkg/util/source/types.go
@@ -25,8 +25,6 @@ type Metadata struct {
 	FromURIs []string
 	// All end URIs of defined routes
 	ToURIs []string
-	// All error handlers URIs of defined routes
-	ErrorHandlerURIs []string
 	// All inferred dependencies required to run the integration
 	Dependencies *strset.Set
 	// ExposesHTTPServices indicates if a route defined by the source is exposed

[camel-k] 21/30: refactor(controller): app properties binding

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 71e06243d44e6533d648b58b4c38e0d7f17a0c45
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 10:24:04 2021 +0200

    refactor(controller): app properties binding
    
    Error handler application properties set via binding
---
 pkg/controller/kameletbinding/common.go        |  2 +-
 pkg/controller/kameletbinding/error_handler.go | 26 +++++++++++--------
 pkg/resources/resources.go                     | 36 +++++++++++++-------------
 pkg/trait/error_handler.go                     | 20 +++++++++++++-
 4 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 45509e1..5da336a 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -81,7 +81,7 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
 	// error handler is optional
-	errorHandler, err := maybeErrorHandler(kameletbinding.Spec.ErrorHandler, bindingContext, &it.Spec)
+	errorHandler, err := maybeErrorHandler(kameletbinding.Spec.ErrorHandler, bindingContext)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not determine error handler")
 	}
diff --git a/pkg/controller/kameletbinding/error_handler.go b/pkg/controller/kameletbinding/error_handler.go
index 0f75670..1d71683 100644
--- a/pkg/controller/kameletbinding/error_handler.go
+++ b/pkg/controller/kameletbinding/error_handler.go
@@ -27,29 +27,33 @@ import (
 	"github.com/pkg/errors"
 )
 
-func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandlerSpec, bindingContext bindings.BindingContext, itSpec *v1.IntegrationSpec) (*bindings.Binding, error) {
-	var errorHandler *bindings.Binding
+func maybeErrorHandler(errHandlConf v1alpha1.ErrorHandlerSpec, bindingContext bindings.BindingContext) (*bindings.Binding, error) {
+	var errorHandlerBinding *bindings.Binding
 	if errHandlConf.RawMessage != nil {
 		errorHandlerSpec, err := parseErrorHandler(errHandlConf.RawMessage)
 		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())
+			errorHandlerBinding, 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 {
+			// Create a new binding otherwise in order to store application properties
+			errorHandlerBinding = &bindings.Binding{
+				URI:                   "error-handler",
+				ApplicationProperties: make(map[string]string),
+			}
 		}
 
-		err = setErrorHandlerConfiguration(itSpec, errorHandlerURI, errorHandlerSpec)
+		err = setErrorHandlerConfiguration(errorHandlerBinding, errorHandlerSpec)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not set integration error handler")
 		}
 
-		return errorHandler, nil
+		return errorHandlerBinding, nil
 	}
 	return nil, nil
 }
@@ -92,16 +96,16 @@ func parseErrorHandler(rawMessage v1.RawMessage) (v1alpha1.ErrorHandler, error)
 	return nil, errors.New("You must provide any supported error handler")
 }
 
-func setErrorHandlerConfiguration(it *v1.IntegrationSpec, errorHandlerURI string, errorHandler v1alpha1.ErrorHandler) error {
+func setErrorHandlerConfiguration(errorHandlerBinding *bindings.Binding, errorHandler v1alpha1.ErrorHandler) error {
 	properties, err := errorHandler.Configuration()
 	if err != nil {
 		return err
 	}
 	for key, value := range properties {
-		it.AddConfiguration("property", fmt.Sprintf("%s=%v", key, value))
+		errorHandlerBinding.ApplicationProperties[key] = fmt.Sprintf("%v", value)
 	}
-	if errorHandler.Type() == v1alpha1.ErrorHandlerTypeDeadLetterChannel && errorHandlerURI != "" {
-		it.AddConfiguration("property", fmt.Sprintf("%s.deadLetterUri=%v", v1alpha1.ErrorHandlerAppPropertiesPrefix, errorHandlerURI))
+	if errorHandler.Type() == v1alpha1.ErrorHandlerTypeDeadLetterChannel && errorHandlerBinding.URI != "" {
+		errorHandlerBinding.ApplicationProperties[fmt.Sprintf("%s.deadLetterUri", v1alpha1.ErrorHandlerAppPropertiesPrefix)] = fmt.Sprintf("%v", errorHandlerBinding.URI)
 	}
 	return nil
 }
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 5c771bb..9f43b93 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -238,19 +238,19 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x6f\xab\x46\x14\xdd\xcf\xaf\x38\x32\x9b\xf7\x24\x1b\xb7\x5d\x55\xee\x8a\x97\xd8\x2d\x6a\x64\x4b\xc6\x69\x94\xe5\x78\xb8\xc0\xad\x61\x2e\x9d\x19\x42\xdc\x5f\x5f\x0d\xb6\x9b\x44\x55\xab\x2e\x32\x2b\x10\x97\xf3\x71\xcf\x99\x04\x8b\xcf\x3b\x2a\xc1\x03\x1b\xb2\x9e\x4a\x04\x41\x68\x08\x59\xaf\x4d\x43\x28\xa4\x0a\xa3\x76\x84\x8d\x0c\xb6\xd4\x81\xc5\xe2\x4b\x56\x6c\xbe\x62\xb0\x25\x39\x88\x25\x88\x43\x27\x8e\x54\x [...]
 		},
-		"/rbac/operator-role-binding-service-binding.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "operator-role-binding-service-binding.yaml",
+		"/rbac/operator-role-binding-podmonitors.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "operator-role-binding-podmonitors.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 1237,
+			uncompressedSize: 1229,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xcf\x6f\xf2\x46\x10\xbd\xef\x5f\xf1\x84\x2f\xdf\x27\x81\x69\x7b\xaa\xe8\xc9\x5f\x02\xad\xd5\x08\x24\x4c\x1a\xe5\xb8\x5e\x0f\xf6\x14\x7b\xc7\xdd\x5d\xc7\xa1\x7f\x7d\xb5\x06\x9a\x44\x55\x2b\x55\xca\xde\x10\x33\xef\xc7\xbc\xe7\x04\x8b\xcf\x7b\x2a\xc1\x03\x1b\xb2\x9e\x2a\x04\x41\x68\x08\x59\xaf\x4d\x43\x28\xe4\x18\x46\xed\x08\x1b\x19\x6c\xa5\x03\x8b\xc5\x97\xac\xd8\x7c\xc5\x60\x2b\x72\x10\x4b\x10\x87\x4e\x1c\xa9\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x72\x36\xbb\xad\xd0\xc0\x06\x2c\xa7\x41\x8e\x34\x35\x96\xa6\x2b\x71\xd8\x21\xb5\x8a\xfb\xeb\x0b\xca\x76\x77\x83\xa2\x45\x0f\xe1\x4d\xd0\xf0\x7d\xcc\x7b\x2c\xb0\xfc\x76\xc7\x14\xf8\xc0\x8e\x7c\xa4\x06\x49\x90\x3a\xc2\x26\x58\xd7\x11\x6a\x39\xa5\xc9\x2a\xe1\x51\x46\xdf\xd8\xc4\xe2\xf1\x66\x53\x3f\xbe\xc5\xe8\x1b\x52\x88\x27\x88\x62\x10\x25\x [...]
 		},
-		"/rbac/operator-role-binding-servicemonitors.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "operator-role-binding-servicemonitors.yaml",
+		"/rbac/operator-role-binding-service-binding.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "operator-role-binding-service-binding.yaml",
 			modTime:          time.Time{},
 			uncompressedSize: 1237,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x52\x36\xeb\x56\x68\x60\x03\x96\xd3\x20\x47\x9a\x1a\x4b\x53\x4b\x1c\x75\x48\xad\xe2\xfe\xfa\x82\xb2\xdd\xdd\xa0\x68\x81\x02\xe1\xcd\xf0\xcc\xfb\x98\xf7\x94\x61\xf9\xed\x9e\xc9\xf0\x81\x1d\xf9\x40\x35\xa2\x20\xb6\x84\x62\xb0\xae\x25\x54\x72\x8a\x93\x55\xc2\x46\x46\x5f\xdb\xc8\xe2\xf1\xa6\xa8\x36\x6f\x31\xfa\x9a\x14\xe2\x09\xa2\xe8\x45\xc9\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xcf\x6f\xf2\x46\x10\xbd\xef\x5f\xf1\x84\x2f\xdf\x27\x81\x69\x7b\xaa\xe8\xc9\x5f\x02\xad\xd5\x08\x24\x4c\x1a\xe5\xb8\x5e\x0f\xf6\x14\x7b\xc7\xdd\x5d\xc7\xa1\x7f\x7d\xb5\x06\x9a\x44\x55\x2b\x55\xca\xde\x10\x33\xef\xc7\xbc\xe7\x04\x8b\xcf\x7b\x2a\xc1\x03\x1b\xb2\x9e\x2a\x04\x41\x68\x08\x59\xaf\x4d\x43\x28\xe4\x18\x46\xed\x08\x1b\x19\x6c\xa5\x03\x8b\xc5\x97\xac\xd8\x7c\xc5\x60\x2b\x72\x10\x4b\x10\x87\x4e\x1c\xa9\x [...]
 		},
 		"/rbac/operator-role-binding-strimzi.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-binding-strimzi.yaml",
@@ -301,6 +301,13 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x53\xc1\x8e\xdb\x46\x0c\xbd\xeb\x2b\x1e\xac\x4b\x02\xac\xe5\xb6\xa7\xc2\x3d\xb9\xc9\x6e\x6b\x34\xb0\x81\x95\xd3\x20\x47\x7a\x44\x4b\xc4\x8e\x86\xea\xcc\x68\x95\xed\xd7\x17\x33\xb6\x13\x6f\xdd\x6d\x2e\x01\xa2\x8b\x68\xf2\x89\x7c\x8f\x8f\x2e\x31\xff\x76\x4f\x51\xe2\x9d\x18\x76\x81\x1b\x44\x45\xec\x18\xab\x81\x4c\xc7\xa8\xf5\x10\x27\xf2\x8c\x3b\x1d\x5d\x43\x51\xd4\xe1\xd5\xaa\xbe\x7b\x8d\xd1\x35\xec\xa1\x8e\xa1\x1e\x [...]
 		},
+		"/rbac/operator-role-podmonitors.yaml": &vfsgen۰CompressedFileInfo{
+			name:             "operator-role-podmonitors.yaml",
+			modTime:          time.Time{},
+			uncompressedSize: 1242,
+
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x8f\xdb\x36\x10\xbd\xf3\x57\x3c\x58\x97\x04\x58\xcb\x6d\x4f\x85\x7b\x72\x37\xbb\xad\xd0\xc0\x06\x56\x4e\x83\x1c\x69\x6a\x2c\x0d\x96\xe2\xb0\x43\x6a\x95\xed\xaf\x2f\x24\xcb\xcd\x1a\xb9\x86\x17\x8f\xc9\xe1\xfb\xe0\x1b\x15\x58\xff\xb8\x65\x0a\x7c\x64\x47\x21\x51\x83\x2c\xc8\x1d\x61\x17\xad\xeb\x08\xb5\x9c\xf3\x68\x95\xf0\x28\x43\x68\x6c\x66\x09\x78\xb7\xab\x1f\xdf\x63\x08\x0d\x29\x24\x10\x44\xd1\x8b\x92\x29\x [...]
+		},
 		"/rbac/operator-role-service-binding.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-service-binding.yaml",
 			modTime:          time.Time{},
@@ -308,13 +315,6 @@ var assets = func() http.FileSystem {
 
 			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xc1\x6e\xdc\x36\x10\xbd\xf3\x2b\x1e\x56\x97\x04\xb0\xe4\xb6\xa7\x62\x7b\xda\x3a\x76\x2b\x34\xd8\x05\xac\x4d\x83\x1c\xb9\xd4\xac\x34\x30\xc5\x51\x87\x94\x15\xf7\xeb\x0b\x6a\xb5\x89\x8d\x5e\xa3\x0b\x47\xe4\xcc\x9b\xf7\xf8\x86\x05\xca\x1f\xf7\x99\x02\x1f\xd9\x51\x88\xd4\x22\x09\x52\x4f\xd8\x8d\xd6\xf5\x84\x46\xce\x69\xb6\x4a\x78\x90\x29\xb4\x36\xb1\x04\xbc\xdb\x35\x0f\xef\x31\x85\x96\x14\x12\x08\xa2\x18\x44\xc9\x [...]
 		},
-		"/rbac/operator-role-servicemonitors.yaml": &vfsgen۰CompressedFileInfo{
-			name:             "operator-role-servicemonitors.yaml",
-			modTime:          time.Time{},
-			uncompressedSize: 1250,
-
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xc1\x8e\xdb\x36\x10\xbd\xf3\x2b\x1e\xac\x4b\x02\xac\xe5\xb6\xa7\xc2\x3d\xb9\x9b\xdd\x56\x68\x60\x03\x2b\xa7\x41\x8e\x34\x35\x96\x06\x4b\x71\xd4\x21\xb5\x8a\xfb\xf5\x85\x68\xb9\xd9\x45\xae\xe1\xc5\x63\x72\x66\xde\x7b\xf3\x46\x05\xd6\x3f\xee\x98\x02\x1f\xd9\x51\x88\xd4\x20\x09\x52\x47\xd8\x0d\xd6\x75\x84\x5a\xce\x69\xb2\x4a\x78\x94\x31\x34\x36\xb1\x04\xbc\xdb\xd5\x8f\xef\x31\x86\x86\x14\x12\x08\xa2\xe8\x45\xc9\x [...]
-		},
 		"/rbac/operator-role-strimzi.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-role-strimzi.yaml",
 			modTime:          time.Time{},
@@ -467,9 +467,9 @@ var assets = func() http.FileSystem {
 		"/traits.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "traits.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 37171,
+			uncompressedSize: 36976,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xed\x72\x1c\xb7\x11\xe0\x7f\x3d\x05\x8a\xb9\x2a\x7e\xd4\xee\x90\x72\xca\xb1\xb3\x77\xba\x14\x2d\x29\x09\x6d\x4b\xe2\x89\x8a\x53\x57\x3a\x57\x16\x3b\xd3\xbb\x0b\x11\x03\x4c\x00\x0c\xa9\xcd\xd5\xbd\xfb\x15\xba\x01\x0c\x66\x77\xb8\x1c\xca\xa6\xcb\xbc\xba\xe4\x87\x45\x72\xa6\xd1\x68\x34\xfa\xbb\x7b\x9c\xe1\xc2\xd9\xd9\xb3\x29\x53\xbc\x86\x19\xe3\xcb\xa5\x50\xc2\x6d\x9e\x31\xd6\x48\xee\x96\xda\xd4\x33\xb6\xe4\xd2\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1c\xb7\xd1\xe0\x77\xfd\x0a\x14\x9f\xab\xe2\x4b\xed\x0c\x29\xa7\x9c\xf8\xf6\x4e\x97\xa2\x25\x25\xa1\x6d\x49\x3c\x51\x71\xea\x4a\xa7\xca\x62\x67\x7a\x77\x21\x62\x80\x09\x80\x21\xb5\xb9\xba\xff\x7e\x85\x6e\x00\x83\xd9\x1d\x2e\x97\xb2\xe9\x32\xaf\x9e\xe4\x83\x45\x72\xa6\xd1\x68\x34\xfa\xbd\x7b\x9c\xe1\xc2\xd9\xe9\xb3\x82\x29\xde\xc0\x94\xf1\xc5\x42\x28\xe1\xd6\xcf\x18\x6b\x25\x77\x0b\x6d\x9a\x29\x5b\x70\x [...]
 		},
 	}
 	fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
@@ -524,8 +524,8 @@ var assets = func() http.FileSystem {
 		fs["/rbac/operator-role-binding-knative.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-leases.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-openshift.yaml"].(os.FileInfo),
+		fs["/rbac/operator-role-binding-podmonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-service-binding.yaml"].(os.FileInfo),
-		fs["/rbac/operator-role-binding-servicemonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding-strimzi.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-binding.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-events.yaml"].(os.FileInfo),
@@ -533,8 +533,8 @@ var assets = func() http.FileSystem {
 		fs["/rbac/operator-role-kubernetes.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-leases.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-openshift.yaml"].(os.FileInfo),
+		fs["/rbac/operator-role-podmonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-service-binding.yaml"].(os.FileInfo),
-		fs["/rbac/operator-role-servicemonitors.yaml"].(os.FileInfo),
 		fs["/rbac/operator-role-strimzi.yaml"].(os.FileInfo),
 		fs["/rbac/user-cluster-role.yaml"].(os.FileInfo),
 		fs["/rbac/user-global-kamelet-viewer-role-binding.yaml"].(os.FileInfo),
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index e705e97..fbd757f 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -83,7 +83,25 @@ func addErrorHandlerAsSource(e *Environment) error {
 		Language: v1.LanguageJavaSource,
 		Type:     v1.SourceTypeErrorHandler,
 	}
-
+	/*
+		flowErrorHandler := map[string]interface{}{
+			"error-handler": map[string]string{
+				"ref": errorHandlerRefName,
+			},
+		}
+		encodedFlowErrorHandler, err := yaml.Marshal(flowErrorHandler)
+		if err != nil {
+			return err
+		}
+		errorHandlerSource := v1.SourceSpec{
+			DataSpec: v1.DataSpec{
+				Name:    "ErrorHandlerSource.yaml",
+				Content: string(encodedFlowErrorHandler),
+			},
+			Language: v1.LanguageYaml,
+			Type:     v1.SourceTypeErrorHandler,
+		}
+	*/
 	e.Integration.Status.AddOrReplaceGeneratedSources(errorHandlerSource)
 
 	return nil

[camel-k] 02/30: doc(example): kameletbinding error handler

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 1cbec513d0304004a8a8d3b97626689c279790d4
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Mar 16 16:18:52 2021 +0100

    doc(example): kameletbinding error handler
---
 .../kamelets/error-handler/error-sink.kamelet.yaml | 44 ++++++++++++++++++
 .../kamelet-binding-error-handler.yaml             | 38 +++++++++++++++
 examples/kamelets/error-handler/readme.md          | 49 ++++++++++++++++++++
 .../error-handler/timer-source.kamelet.yaml        | 54 ++++++++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/examples/kamelets/error-handler/error-sink.kamelet.yaml b/examples/kamelets/error-handler/error-sink.kamelet.yaml
new file mode 100644
index 0000000..e35a54d
--- /dev/null
+++ b/examples/kamelets/error-handler/error-sink.kamelet.yaml
@@ -0,0 +1,44 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: error-sink
+  annotations:
+    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAACcBJREFUeJzt3XmsHVUdwPHva21poWGTUpAiVRQSFjWAyi5LcCmKLCEouLwQccMgGsISEkQRXMIfSKMGhQSMCCibkRIgghQEF4RIQYtG4YFsraRlb6G+1j9+94a50/fmvuW+OTN3vp9kkrnnzj3zu+/N786ZmTNnQJIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZKkfjOQOoAKGQA+DJwAvBfYCpieNKKJexk4E/h56kDUH94O3AOs76NpHfDlXv6R1Ey7ACtIv0FP1XRa7/5Uapo5wL9JvxFP9fSNXv3Bmu [...]
+  labels:
+    camel.apache.org/kamelet.type: "sink"
+spec:
+  definition:
+    title: "Error Log Sink"
+    description: "Consume events from a channel"
+    required:
+      - defaultMessage
+    properties:
+      defaultMessage:
+        title: Message
+        description: The default message to log
+        type: string
+        example: "error while checking the source"    
+  flow:
+    from:
+      uri: kamelet:source
+      steps:
+      - set-body:
+          constant: "{{defaultMessage}}"
+      - to: "log:error-sink"
diff --git a/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
new file mode 100644
index 0000000..d731d1f
--- /dev/null
+++ b/examples/kamelets/error-handler/kamelet-binding-error-handler.yaml
@@ -0,0 +1,38 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: http-error-source
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: timer-source
+    properties:
+      message: "Hello world!"
+  sink:
+    uri: https://log-source/failing-service
+  errorHandler:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: error-sink
+    properties:
+     defaultMessage: "ERROR ERROR!"      
diff --git a/examples/kamelets/error-handler/readme.md b/examples/kamelets/error-handler/readme.md
new file mode 100644
index 0000000..5438050
--- /dev/null
+++ b/examples/kamelets/error-handler/readme.md
@@ -0,0 +1,49 @@
+# Kamelets Binding Error Handler example
+This example shows how to create a simple _timer-source_ `kamelet` bound to a failing sink in a `KameletBinding`. With the support of the `ErrorHandler` we will be able to redirect all errors to a `Dead Letter Channel` _error-sink_ `Kamelet`.
+
+## Timer Source Kamelet
+First of all, you must install the _timer-source_ Kamelet defined in `timer-source.kamelet.yaml` file:
+```
+$ kubectl apply -f timer-source.kamelet.yaml
+```
+You can check the newly created `kamelet` checking the list of kamelets available:
+```
+$ kubectl get kamelets
+
+NAME                   PHASE
+timer-source           Ready
+```
+## Error Sink Kamelet
+Now it's the turn of installing the _error-sink_ Kamelet defined in `error-sink.kamelet.yaml` file:
+```
+$ kubectl apply -f error-sink.kamelet.yaml
+```
+You can check the newly created `kamelet` checking the list of kamelets available:
+```
+$ kubectl get kamelets
+
+NAME           PHASE
+error-sink     Ready
+timer-source   Ready
+```
+## Error Handler Kamelet Binding
+We can create a `KameletBinding` which is triggered by the _timer-source_ `Kamelet` and define a fake sink URI in order to make it fail on purpose. Then we can configure an _errorHandler_ as defined in `kamelet-binding-error-handler.yaml` file:
+```
+  errorHandler:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: log-sink
+    properties:
+     defaultMessage: "ERROR ERROR!" 
+```
+Execute the following command to start the `Integration`:
+```
+kubectl apply -f kamelet-binding-error-handler.yaml
+```
+As soon as the `Integration` starts, it will log a message error for every failure it will print:
+```
+[1] 2021-03-16 15:11:33,099 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
+[1] 2021-03-16 15:11:33,988 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
+[1] 2021-03-16 15:11:34,988 INFO  [error-sink] (Camel (camel-1) thread #0 - timer://tick) Exchange[ExchangePattern: InOnly, BodyType: String, Body: ERROR ERROR!]
+```
\ No newline at end of file
diff --git a/examples/kamelets/error-handler/timer-source.kamelet.yaml b/examples/kamelets/error-handler/timer-source.kamelet.yaml
new file mode 100644
index 0000000..f837fb5
--- /dev/null
+++ b/examples/kamelets/error-handler/timer-source.kamelet.yaml
@@ -0,0 +1,54 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: timer-source
+  annotations:
+    camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm [...]
+  labels:
+    camel.apache.org/kamelet.type: "source"
+spec:
+  definition:
+    title: "Timer Source"
+    description: "Produces periodic events with a custom payload"
+    required:
+      - message
+    properties:
+      period:
+        title: Period
+        description: The interval between two events
+        type: integer
+        default: 1000
+      message:
+        title: Message
+        description: The message to generate
+        type: string
+        example: "hello world"
+  types:
+    out:
+      mediaType: text/plain
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "{{period}}"
+      steps:
+      - set-body:
+          constant: "{{message}}"
+      - to: "kamelet:sink"

[camel-k] 09/30: refactor(trait): error handler kamelet

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 3b8ae4a22a6dbcca65c2bfd4f580020990c02b4b
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 10:15:17 2021 +0200

    refactor(trait): error handler kamelet
    
    Just look for a possible error handler kamelet, it it was configured
---
 pkg/controller/kameletbinding/common.go | 22 +++++++---
 pkg/trait/kamelets.go                   | 78 ++++++++++++++-------------------
 2 files changed, 48 insertions(+), 52 deletions(-)

diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go
index 13e13fe..06b5b76 100644
--- a/pkg/controller/kameletbinding/common.go
+++ b/pkg/controller/kameletbinding/common.go
@@ -80,13 +80,18 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 		return nil, errors.Wrap(err, "could not determine sink URI")
 	}
 	var errorHandler *bindings.Binding
-	if kameletbinding.Spec.ErrorHandler.Endpoint.Ref != nil || kameletbinding.Spec.ErrorHandler.Endpoint.URI != nil {
-		errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler.Endpoint)
-		if err != nil {
-			return nil, errors.Wrap(err, "could not determine error handler URI")
+	if kameletbinding.Spec.ErrorHandler.Type != "" {
+		errorHandlerURI := ""
+		if kameletbinding.Spec.ErrorHandler.Endpoint.Ref != nil || kameletbinding.Spec.ErrorHandler.Endpoint.URI != nil {
+			errorHandler, err = bindings.Translate(bindingContext, bindings.EndpointContext{Type: v1alpha1.EndpointTypeErrorHandler}, kameletbinding.Spec.ErrorHandler.Endpoint)
+			if err != nil {
+				return nil, errors.Wrap(err, "could not determine error handler URI")
+			}
+
+			errorHandlerURI = errorHandler.URI
 		}
 
-		err = setIntegrationErrorHandler(&it.Spec, errorHandler, kameletbinding.Spec.ErrorHandler)
+		err = setIntegrationErrorHandler(&it.Spec, errorHandlerURI, kameletbinding.Spec.ErrorHandler)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not set integration error handler")
 		}
@@ -159,12 +164,15 @@ func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	return &it, nil
 }
 
-func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandler *bindings.Binding, errorHandlerSpec v1alpha1.ErrorHandler) error {
+func setIntegrationErrorHandler(it *v1.IntegrationSpec, errorHandlerURI string, errorHandlerSpec v1alpha1.ErrorHandler) error {
 	it.ErrorHandler = v1.ErrorHandlerSpec{
-		URI:  errorHandler.URI,
 		Type: string(errorHandlerSpec.Type),
 	}
 
+	if errorHandlerURI != "" {
+		it.ErrorHandler.URI = errorHandlerURI
+	}
+
 	return nil
 }
 
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 190c17e..57ec4b5 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -105,7 +105,6 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 				util.StringSliceUniqueConcat(&kamelets, extractKamelets(meta.ToURIs))
 				return true
 			})
-			sort.Strings(kamelets)
 		}
 		// Check if a Kamelet is configured as default error handler
 		if e.Integration.Spec.ErrorHandler.URI != "" {
@@ -114,21 +113,24 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) {
 			}
 		}
 
-		t.List = strings.Join(kamelets, ",")
+		if len(kamelets) > 0 {
+			sort.Strings(kamelets)
+			t.List = strings.Join(kamelets, ",")
+		}
 	}
 
-	return t.declaredKamelets(), nil
-}
-
-func (t *kameletsTrait) declaredKamelets() bool {
-	return len(t.getKameletKeys()) > 0
+	return len(t.getKameletKeys()) > 0, nil
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
 <<<<<<< HEAD
+<<<<<<< HEAD
 
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseRunning) {
 =======
+=======
+
+>>>>>>> refactor(trait): error handler kamelet
 	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
 >>>>>>> refactor(trait): integration error handler spec
 		if err := t.addKamelets(e); err != nil {
@@ -146,52 +148,41 @@ func (t *kameletsTrait) Apply(e *Environment) error {
 }
 
 func (t *kameletsTrait) addKamelets(e *Environment) error {
-	if t.declaredKamelets() {
+	kameletKeys := t.getKameletKeys()
+	if len(kameletKeys) > 0 {
 		repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
 		if err != nil {
 			return err
 		}
-
-		// Declared kamelets
 		for _, k := range t.getKameletKeys() {
-			err := initializeKamelet(repo, e, k, t, v1.SourceTypeTemplate)
+			kamelet, err := repo.Get(e.C, k)
 			if err != nil {
 				return err
 			}
-		}
-
-		// resort dependencies
-		sort.Strings(e.Integration.Status.Dependencies)
-	}
-	return nil
-}
+			if kamelet == nil {
+				return fmt.Errorf("kamelet %s not found in any of the defined repositories: %s", k, repo.String())
+			}
 
-func initializeKamelet(repo repository.KameletRepository, e *Environment, k string, t *kameletsTrait, sourceType v1.SourceType) error {
-	kamelet, err := repo.Get(e.C, k)
-	if err != nil {
-		return err
-	}
-	if kamelet == nil {
-		return fmt.Errorf("kamelet %s not found in any of the defined repositories: %s", k, repo.String())
-	}
+			// Initialize remote kamelets
+			kamelet, err = kameletutils.Initialize(kamelet)
+			if err != nil {
+				return err
+			}
 
-	// Initialize remote kamelets
-	kamelet, err = kameletutils.Initialize(kamelet)
-	if err != nil {
-		return err
-	}
+			if kamelet.Status.Phase != v1alpha1.KameletPhaseReady {
+				return fmt.Errorf("kamelet %q is not %s: %s", k, v1alpha1.KameletPhaseReady, kamelet.Status.Phase)
+			}
 
-	if kamelet.Status.Phase != v1alpha1.KameletPhaseReady {
-		return fmt.Errorf("kamelet %q is not %s: %s", k, v1alpha1.KameletPhaseReady, kamelet.Status.Phase)
-	}
+			if err := t.addKameletAsSource(e, kamelet); err != nil {
+				return err
+			}
 
-	if err := t.addKameletAsSource(e, kamelet, sourceType); err != nil {
-		return err
+			// Adding dependencies from Kamelets
+			util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, kamelet.Spec.Dependencies)
+		}
+		// resort dependencies
+		sort.Strings(e.Integration.Status.Dependencies)
 	}
-
-	// Adding dependencies from Kamelets
-	util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, kamelet.Spec.Dependencies)
-
 	return nil
 }
 
@@ -239,7 +230,7 @@ func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
 	return nil
 }
 
-func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet, sourceType v1.SourceType) error {
+func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet) error {
 	sources := make([]v1.SourceSpec, 0)
 
 	if kamelet.Spec.Flow != nil {
@@ -260,7 +251,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
 				Content: string(flowData),
 			},
 			Language:      v1.LanguageYaml,
-			Type:          sourceType,
+			Type:          v1.SourceTypeTemplate,
 			PropertyNames: propertyNames,
 		}
 		flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
@@ -271,9 +262,6 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
 	}
 
 	for idx, s := range kamelet.Spec.Sources {
-		if sourceType == v1.SourceTypeErrorHandler {
-			s.Type = sourceType
-		}
 		intSource, err := integrationSourceFromKameletSource(e, kamelet, s, fmt.Sprintf("%s-kamelet-%s-%03d", e.Integration.Name, kamelet.Name, idx))
 		if err != nil {
 			return err

[camel-k] 12/30: doc(trait): error-handler generated doc

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 0aae94245ba436fb6a8cda3765bb7bbfa435fb0f
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Apr 21 16:12:32 2021 +0200

    doc(trait): error-handler generated doc
---
 deploy/traits.yaml                           |  9 ++++++++
 docs/modules/ROOT/nav.adoc                   |  1 +
 docs/modules/traits/pages/error-handler.adoc | 32 ++++++++++++++++++++++++++++
 pkg/trait/error_handler.go                   |  5 ++---
 pkg/trait/trait_test.go                      |  2 +-
 5 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index 75522d2..0c567dd 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -271,6 +271,15 @@ traits:
     type: bool
     description: Enables injection of `NAMESPACE` and `POD_NAME` environment variables
       (default `true`)
+- name: error-handler
+  platform: true
+  profiles:
+  - Kubernetes
+  - Knative
+  - OpenShift
+  description: The error-handler is a platform trait used to inject Error Handler
+    source into the integration runtime.
+  properties: []
 - name: gc
   platform: false
   profiles:
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index ea9558a..e3d322e 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -41,6 +41,7 @@
 ** xref:traits:deployer.adoc[Deployer]
 ** xref:traits:deployment.adoc[Deployment]
 ** xref:traits:environment.adoc[Environment]
+** xref:traits:error-handler.adoc[Error Handler]
 ** xref:traits:gc.adoc[Gc]
 ** xref:traits:ingress.adoc[Ingress]
 ** xref:traits:istio.adoc[Istio]
diff --git a/docs/modules/traits/pages/error-handler.adoc b/docs/modules/traits/pages/error-handler.adoc
new file mode 100755
index 0000000..0c38c7d
--- /dev/null
+++ b/docs/modules/traits/pages/error-handler.adoc
@@ -0,0 +1,32 @@
+= Error Handler Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The error-handler is a platform trait used to inject Error Handler source into the integration runtime.
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
+
+WARNING: The error-handler trait is a *platform trait*: disabling it may compromise the platform functionality.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+[source,console]
+----
+$ kamel run --trait error-handler.[key]=[value] integration.groovy
+----
+The following configuration options are available:
+
+[cols="2m,1m,5a"]
+|===
+|Property | Type | Description
+
+| error-handler.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common property.
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/pkg/trait/error_handler.go b/pkg/trait/error_handler.go
index 228ed12..ef93d67 100644
--- a/pkg/trait/error_handler.go
+++ b/pkg/trait/error_handler.go
@@ -23,17 +23,16 @@ import (
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-// The error handler is a platform trait used to inject Error Handler source into the integration runtime.
+// The error-handler is a platform trait used to inject Error Handler source into the integration runtime.
 //
 // +camel-k:trait=error-handler
 type errorHandlerTrait struct {
 	BaseTrait `property:",squash"`
-	Auto      *bool `property:"auto"`
 }
 
 func newErrorHandlerTrait() Trait {
 	return &errorHandlerTrait{
-		BaseTrait: NewBaseTrait("errorHandler", 500),
+		BaseTrait: NewBaseTrait("error-handler", 500),
 	}
 }
 
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index b8fdca8..e1bea3b 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -507,7 +507,7 @@ func TestOnlySomeTraitsInfluenceBuild(t *testing.T) {
 
 func TestOnlySomeTraitsArePlatform(t *testing.T) {
 	c := NewTraitTestCatalog()
-	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "errorHandler", "kamelets", "openapi", "owner", "platform", "quarkus"}
+	platformTraits := []string{"builder", "camel", "jvm", "container", "dependencies", "deployer", "deployment", "environment", "error-handler", "kamelets", "openapi", "owner", "platform", "quarkus"}
 
 	for _, trait := range c.allTraits() {
 		if trait.IsPlatformTrait() {

[camel-k] 27/30: doc(kamelets): kamelet bindings error handler

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 8f9108672e1854357404c62295917258a34af581
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Apr 27 14:55:20 2021 +0200

    doc(kamelets): kamelet bindings error handler
---
 .../kamelets/kameletbindings-error-handler.adoc    | 156 +++++++++++++++++++++
 .../modules/ROOT/pages/kamelets/kamelets-user.adoc |   4 +
 docs/modules/ROOT/pages/kamelets/kamelets.adoc     |   1 +
 pkg/resources/resources.go                         |  14 +-
 4 files changed, 168 insertions(+), 7 deletions(-)

diff --git a/docs/modules/ROOT/pages/kamelets/kameletbindings-error-handler.adoc b/docs/modules/ROOT/pages/kamelets/kameletbindings-error-handler.adoc
new file mode 100644
index 0000000..fe3f1ce
--- /dev/null
+++ b/docs/modules/ROOT/pages/kamelets/kameletbindings-error-handler.adoc
@@ -0,0 +1,156 @@
+[[kameletbindings-error-handler]]
+= Kamelet Bindings Error Handler
+
+`Kamelet Binding`s offer a mechanism to specify an error policy to adopt in case an event produced by a `source` or consumed by a `sink`. Through the definition of an `errorHandler` you will be able to apply certain logic to the failing event, such as simply logging, ignoring the event or posting the event to a `Dead Letter Channel`.
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source: # <1>
+...
+  sink: # <2>
+...
+  errorHandler: # <3>
+----
+<1> Reference to the source that provides data
+<2> Reference to the sink where data should be sent to
+<3> Error Handler Configuration
+
+[[kameletbindings-error-handler-types]]
+== Error Handler Types
+
+We have different types of error handler: `ǹone`, `log`, `dead-letter-channel`, `bean`, `ref`. The `errorHandler` parameter is optional. The runtime will use the configuration to create an https://camel.apache.org/manual/latest/error-handler.html[Error Handler] as specified by Apache Camel.
+
+[[kameletbindings-error-handler-none]]
+=== No error handler
+
+There may be certain cases where you want to just ignore any failure happening on your integration. In this situation just use a `ǹone` error handler. Under the hood the configuration will create a https://camel.apache.org/manual/latest/error-handler.html#ErrorHandler-NoErrorHandler[`No` error handler builder]. 
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source:
+...
+  sink: 
+...
+  errorHandler: 
+    none: # <1>
+----
+<1> `none` error handler does not expect any configuration
+
+[[kameletbindings-error-handler-log]]
+=== Log error handler
+
+Apache Camel offers a default behavior for handling any failure: log to standard output. However you can use the `log` error handler to specify other behaviors such as redelivery or delay policy. Under the hood the configuration will create a https://camel.apache.org/manual/latest/error-handler.html#_defaulterrorhandler[`Default` error handler builder].
+
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source:
+...
+  sink: 
+...
+  errorHandler: 
+    log:
+      parameters: # <1>
+        maximumRedeliveries: 3
+        redeliveryDelay: 2000
+----
+<1> Parameters belonging to the `log` error handler type
+
+[[kameletbindings-error-handler-dlc]]
+=== Dead Letter Channel error handler
+
+The `Dead Letter Channel` is probably the most interesting error handler type as it allows you to redirect any failing event to any other component, such as a third party URI, a queue or even another `Kamelet` which will be performing certain logic with the failing event. Under the hood the configuration will create a https://camel.apache.org/manual/latest/error-handler.html#_dead_letter_channel[`Dead Letter Channel` error handler builder].
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source:
+...
+  sink: 
+...
+  errorHandler: 
+    dead-letter-channel:
+      endpoint: 
+        ref: # <1>
+          kind: Kamelet
+          apiVersion: camel.apache.org/v1alpha1
+          name: error-handler
+        properties:
+          message: "ERROR!" # <2>
+          ...
+      parameters:
+        maximumRedeliveries: 1 # <3>
+        ... 
+----
+<1> You can use `ref` or `uri`. `ref` will be interpreted by the operator according the `kind`, `apiVersion` and `name`. You can use any `Kamelet`, `KafkaTopic` channel or `Knative` destination.
+<2> Properties belonging to the endpoint (in this example, to the `Kamelet` named error handler)
+<3> Parameters belonging to the `dead-letter-channel` error handler type
+
+[[kameletbindings-error-handler-bean]]
+=== Bean error handler
+
+With the `Bean` error handler you can extend the functionality of the Error Handler by providing a custom bean to be used as Error Handler.
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source:
+...
+  sink: 
+...
+  errorHandler: 
+    bean:
+      type: "org.apache.camel.builder.DeadLetterChannelBuilder" # <1>
+      properties: # <2>
+        deadLetterUri: log:error
+        ... 
+----
+<1> Fully qualified name of the ErrorHandlerBuilder
+<2> Properties expected by your type
+
+[[kameletbindings-error-handler-ref]]
+=== Ref error handler
+
+With the `Ref` error handler you can use any `Bean` that is expected to be found in the Camel registry at runtime.
+
+[source,yaml]
+----
+apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  name: my-kamelet-binding
+spec:
+  source:
+...
+  sink: 
+...
+  errorHandler: 
+    ref: my-custom-builder # <1>
+... 
+----
+<1> The name of the bean to be looked up at runtime
+
+NOTE: make sure to have the `ref` correctly bind at runtime.
\ No newline at end of file
diff --git a/docs/modules/ROOT/pages/kamelets/kamelets-user.adoc b/docs/modules/ROOT/pages/kamelets/kamelets-user.adoc
index 4a334cb..ef48761 100644
--- a/docs/modules/ROOT/pages/kamelets/kamelets-user.adoc
+++ b/docs/modules/ROOT/pages/kamelets/kamelets-user.adoc
@@ -356,6 +356,10 @@ This KameletBinding explicitly defines an URI where data is going to be pushed.
 NOTE: the `uri` option is also conventionally used in Knative to specify a non-kubernetes destination.
 To comply with the Knative specifications, in case an "http" or "https" URI is used, Camel will send https://cloudevents.io/[CloudEvents] to the destination.
 
+=== Error Handling
+
+You can configure an error handler in order to specify what to do when some event ends up with failure. See xref:kamelets/kameletbindings-error-handler.adoc[Kamelet Bindings Error Handler User Guide] for more detail.
+
 [[kamelets-specification]]
 == Kamelet Specification
 
diff --git a/docs/modules/ROOT/pages/kamelets/kamelets.adoc b/docs/modules/ROOT/pages/kamelets/kamelets.adoc
index 6ba3ff5..c0d0327 100644
--- a/docs/modules/ROOT/pages/kamelets/kamelets.adoc
+++ b/docs/modules/ROOT/pages/kamelets/kamelets.adoc
@@ -4,4 +4,5 @@
 This section of the documentation contains information about Kamelets from both a user and a developer point of view:
 
 - The xref:kamelets/kamelets-user.adoc[Kamelets User Guide] is for users that want to use Kamelets for connecting systems with their applications
+- The xref:kamelets/kameletbindings-error-handler.adoc[Kamelet Bindings Error Handler User Guide] explains how to configure an error handler on a `Kamelet Binding`
 - The xref:kamelets/kamelets-dev.adoc[Kamelets Developer Guide] is a reference for developers that want to create new Kamelets and share them with users
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 9f43b93..94a6ac4 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -106,16 +106,16 @@ var assets = func() http.FileSystem {
 		"/crd/bases/camel.apache.org_integrations.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_integrations.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 24066,
+			uncompressedSize: 23405,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\x5d\x73\xe3\xb8\x91\xef\xfa\x15\x5d\xf6\xc3\xec\x56\x49\x54\x66\x26\xa9\xbb\xf2\x3d\x79\x3d\x33\x17\xdd\x78\x6d\x97\xe5\xc9\xd6\x56\x2a\x0f\x10\xd9\x12\x11\x83\x00\x0f\x00\x25\x2b\xa9\xfc\xf7\xab\x6e\x90\x14\x29\x91\xb4\xc6\x9e\xdd\xcd\x25\xe2\xcb\x8c\x49\xa0\xd1\xdf\x5f\x00\x74\x0e\x93\x6f\xf7\x8c\xce\xe1\x5a\xc6\xa8\x1d\x26\xe0\x0d\xf8\x14\xe1\x32\x17\x71\x8a\x30\x37\x4b\xbf\x11\x16\xe1\x93\x29\x74\x22\xbc\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\x5d\x73\xdb\xba\x95\xef\xfa\x15\x67\xec\x87\xdc\xcc\x48\x54\x93\xb4\xb3\x3b\xde\x27\xd7\x89\x77\xb5\xf1\xb5\x33\x96\xd3\x3b\x77\x3a\x7d\x80\xc8\x43\x0a\x35\x08\x70\x01\xd0\xb2\xda\xe9\x7f\xdf\x39\x07\x24\x45\x4a\xa4\xac\xc8\xb9\xf7\x76\xbb\xe2\x4b\x62\x12\x38\x38\xdf\x5f\x00\x74\x0e\x93\xef\xf7\x8c\xce\xe1\x46\xc6\xa8\x1d\x26\xe0\x0d\xf8\x25\xc2\x65\x21\xe2\x25\xc2\xdc\xa4\x7e\x25\x2c\xc2\xb5\x29\x75\x22\xbc\x [...]
 		},
 		"/crd/bases/camel.apache.org_kameletbindings.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kameletbindings.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 56150,
+			uncompressedSize: 55181,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x81\x48\x8e\x93\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\xfb\xfa\xb5\x9b\x06\x49\x7a\x87\x7b\x6d\x0f\xa0\xa5\xb1\xcd\x8b\x44\xea\x48\x2a\x8e\xdf\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x89\x72\xec\x6e\x0b\x88\x40\xd1\xd8\xa6\x86\x33\xc3\x99\xe1\x70\xc8\x8f\x7d\x00\xde\xf6\xda\xde\x01\xbc\xa7\x01\x32\x89\x21\x28\x0e\x6a\x8a\x70\x96\x90\x60\x8a\x70\xc3\xc7\x6a\x46\x04\xc2\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xf1\x6f\xdb\x38\xf2\xef\xef\xf9\x2b\x06\xc9\x01\x6d\x01\x4b\x8e\xe3\xb4\xbb\xeb\xf7\x43\x91\x26\xdb\x7b\x7e\xed\xa6\x45\x92\xde\xe1\x5e\xdb\x03\x68\x69\x6c\xf3\x22\x91\x3a\x92\x8a\xe3\xef\xb6\xff\xfb\x17\x24\x25\x59\x76\x2c\x99\x72\xec\x6e\x0a\x88\xc0\x62\x6b\x8b\x1a\xce\x0c\x87\xc3\x99\x21\x3f\xce\x11\x78\xbb\x6b\x07\x47\xf0\x9e\x06\xc8\x24\x86\xa0\x38\xa8\x29\xc2\x59\x42\x82\x29\xc2\x35\x1f\xab\x19\x11\x08\x [...]
 		},
 		"/crd/bases/camel.apache.org_kamelets.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "camel.apache.org_kamelets.yaml",
@@ -144,7 +144,7 @@ var assets = func() http.FileSystem {
 			modTime:          time.Time{},
 			uncompressedSize: 2397,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x55\xc1\x6e\xe3\x36\x10\xbd\xeb\x2b\x1e\xac\xcb\x2e\x10\xdb\xc9\x02\x05\x16\xea\x49\x4d\x9c\xc6\x68\x6a\x1b\x96\xb7\xc1\x9e\x0a\x9a\x1a\x4b\x44\x28\x8e\x4a\x52\xf6\xaa\x5f\x5f\x50\xb6\x1c\xdb\x9b\xa6\x3d\x04\x58\x9e\x2c\xcd\xcc\x9b\xf7\x66\x9e\xe8\x18\xc3\xf7\x3b\x51\x8c\x47\x25\xc9\x38\xca\xe1\x19\xbe\x24\xa4\xb5\x90\x25\x21\xe3\x8d\xdf\x09\x4b\xb8\xe7\xc6\xe4\xc2\x2b\x36\xf8\x90\x66\xf7\x1f\xd1\x98\x9c\x2c\xd8\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x55\xc1\x6e\xe3\x36\x10\xbd\xeb\x2b\x1e\xac\xcb\x2e\x10\xdb\xc9\xa2\x87\x85\x7a\x52\x13\xa7\x31\x9a\xda\x86\xe5\x6d\xb0\xa7\x82\xa6\xc6\x12\x11\x8a\xa3\x92\x94\xbd\xea\xd7\x17\x94\x2d\xc7\xf6\xa6\x69\x0f\x01\x96\x27\x4b\x33\xf3\xe6\xbd\x99\x27\x3a\xc6\xf0\xfd\x4e\x14\xe3\x51\x49\x32\x8e\x72\x78\x86\x2f\x09\x69\x2d\x64\x49\xc8\x78\xe3\x77\xc2\x12\xee\xb9\x31\xb9\xf0\x8a\x0d\x3e\xa4\xd9\xfd\x47\x34\x26\x27\x0b\x36\x [...]
 		},
 		"/manager/operator-service-account.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "operator-service-account.yaml",
@@ -467,9 +467,9 @@ var assets = func() http.FileSystem {
 		"/traits.yaml": &vfsgen۰CompressedFileInfo{
 			name:             "traits.yaml",
 			modTime:          time.Time{},
-			uncompressedSize: 36976,
+			uncompressedSize: 36744,
 
-			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1c\xb7\xd1\xe0\x77\xfd\x0a\x14\x9f\xab\xe2\x4b\xed\x0c\x29\xa7\x9c\xf8\xf6\x4e\x97\xa2\x25\x25\xa1\x6d\x49\x3c\x51\x71\xea\x4a\xa7\xca\x62\x67\x7a\x77\x21\x62\x80\x09\x80\x21\xb5\xb9\xba\xff\x7e\x85\x6e\x00\x83\xd9\x1d\x2e\x97\xb2\xe9\x32\xaf\x9e\xe4\x83\x45\x72\xa6\xd1\x68\x34\xfa\xbd\x7b\x9c\xe1\xc2\xd9\xe9\xb3\x82\x29\xde\xc0\x94\xf1\xc5\x42\x28\xe1\xd6\xcf\x18\x6b\x25\x77\x0b\x6d\x9a\x29\x5b\x70\x [...]
+			compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1c\xb7\xd1\xe0\x77\xfd\x0a\x14\x9f\xab\xe2\x4b\xed\x0e\x29\xa7\x9c\xf8\xf6\x4e\x97\xa2\x25\x25\xa1\x6d\x49\x3c\x51\x71\xea\x4a\xa7\xca\x62\x67\x7a\x77\x21\x62\x80\x09\x80\x59\x6a\x73\x75\xff\xfd\x0a\xdd\x00\x06\x33\x3b\x24\x97\xb2\xe9\x32\xaf\x9e\xe4\x83\x45\x72\xa6\xd1\x68\x34\xfa\xbd\x7b\x9c\xe1\xc2\xd9\xd9\xb3\x29\x53\xbc\x86\x19\xe3\xcb\xa5\x50\xc2\x6d\x9f\x31\xd6\x48\xee\x96\xda\xd4\x33\xb6\xe4\x [...]
 		},
 	}
 	fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{