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 <[email protected]> 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)
