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 2020/09/17 09:09:58 UTC

[camel-k] 03/21: kamelets: improving kamelet format

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

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

commit f1533fe73a9429b3251a12904bf298d7d2d2b1d9
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Tue Jun 23 21:26:41 2020 +0200

    kamelets: improving kamelet format
---
 examples/kamelets/timer.kamelet.yaml             |  24 +-
 pkg/apis/camel/group.go                          |   6 +
 pkg/apis/camel/v1alpha1/doc.go                   |   4 +
 pkg/apis/camel/v1alpha1/jsonschema_types.go      | 260 +++++++++++++++
 pkg/apis/camel/v1alpha1/kamelet_types.go         |  71 ++--
 pkg/apis/camel/v1alpha1/kamelet_types_support.go |  17 +
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 407 ++++++++++++++++++++++-
 pkg/controller/add_kamelet.go                    |  26 ++
 8 files changed, 768 insertions(+), 47 deletions(-)

diff --git a/examples/kamelets/timer.kamelet.yaml b/examples/kamelets/timer.kamelet.yaml
index 9a2ec5d..91848d0 100644
--- a/examples/kamelets/timer.kamelet.yaml
+++ b/examples/kamelets/timer.kamelet.yaml
@@ -3,17 +3,21 @@ kind: Kamelet
 metadata:
   name: timer
 spec:
-  displayName: "Timer"
-  description: "Produces produces periodic events with a custom payload"
-  parameters:
-    - name: message
-      description: The message to generate
-      schema:
+  definition:
+    title: "Timer"
+    description: "Produces produces periodic events with a custom payload"
+    required:
+      - message
+    properties:
+      message:
+        title: Message
+        description: The message to generate
         type: string
-  produces:
-    type: text.types.camel.apache.org
-    schema:
-      content:
+  types:
+    out:
+      mediaType: application/json
+      schema:
+        id: text.camel.apache.org
         type: string
   flow:
     from:
diff --git a/pkg/apis/camel/group.go b/pkg/apis/camel/group.go
new file mode 100644
index 0000000..90958df
--- /dev/null
+++ b/pkg/apis/camel/group.go
@@ -0,0 +1,6 @@
+// Package camel contains camel API versions.
+//
+// This file ensures Go source parsers acknowledge the camel package
+// and any child packages. It can be removed if any other Go source files are
+// added to this package.
+package camel
diff --git a/pkg/apis/camel/v1alpha1/doc.go b/pkg/apis/camel/v1alpha1/doc.go
new file mode 100644
index 0000000..102912e
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/doc.go
@@ -0,0 +1,4 @@
+// Package v1alpha1 contains API Schema definitions for the camel v1alpha1 API group
+// +k8s:deepcopy-gen=package,register
+// +groupName=camel.apache.org
+package v1alpha1
diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go b/pkg/apis/camel/v1alpha1/jsonschema_types.go
new file mode 100644
index 0000000..6ebdf1e
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go
@@ -0,0 +1,260 @@
+/*
+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.
+*/
+
+// NOTE: this file has been originally copied from https://github.com/kubernetes/apiextensions-apiserver/blob/33bb2d8b009bae408e40818a93877459efeb4cb1/pkg/apis/apiextensions/v1/types_jsonschema.go
+
+package v1alpha1
+
+// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
+type JSONSchemaProps struct {
+	ID          string        `json:"id,omitempty" protobuf:"bytes,1,opt,name=id"`
+	Schema      JSONSchemaURL `json:"$schema,omitempty" protobuf:"bytes,2,opt,name=schema"`
+	Ref         *string       `json:"$ref,omitempty" protobuf:"bytes,3,opt,name=ref"`
+	Description string        `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
+	Type        string        `json:"type,omitempty" protobuf:"bytes,5,opt,name=type"`
+
+	// format is an OpenAPI v3 format string. Unknown formats are ignored. The following formats are validated:
+	//
+	// - 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.
+	Format string `json:"format,omitempty" protobuf:"bytes,6,opt,name=format"`
+
+	Title string `json:"title,omitempty" protobuf:"bytes,7,opt,name=title"`
+	// default is a default value for undefined object fields.
+	// Defaulting is a beta feature under the CustomResourceDefaulting feature gate.
+	// Defaulting requires spec.preserveUnknownFields to be false.
+	Default              *JSON                      `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
+	Maximum              *float64                   `json:"maximum,omitempty" protobuf:"bytes,9,opt,name=maximum"`
+	ExclusiveMaximum     bool                       `json:"exclusiveMaximum,omitempty" protobuf:"bytes,10,opt,name=exclusiveMaximum"`
+	Minimum              *float64                   `json:"minimum,omitempty" protobuf:"bytes,11,opt,name=minimum"`
+	ExclusiveMinimum     bool                       `json:"exclusiveMinimum,omitempty" protobuf:"bytes,12,opt,name=exclusiveMinimum"`
+	MaxLength            *int64                     `json:"maxLength,omitempty" protobuf:"bytes,13,opt,name=maxLength"`
+	MinLength            *int64                     `json:"minLength,omitempty" protobuf:"bytes,14,opt,name=minLength"`
+	Pattern              string                     `json:"pattern,omitempty" protobuf:"bytes,15,opt,name=pattern"`
+	MaxItems             *int64                     `json:"maxItems,omitempty" protobuf:"bytes,16,opt,name=maxItems"`
+	MinItems             *int64                     `json:"minItems,omitempty" protobuf:"bytes,17,opt,name=minItems"`
+	UniqueItems          bool                       `json:"uniqueItems,omitempty" protobuf:"bytes,18,opt,name=uniqueItems"`
+	MultipleOf           *float64                   `json:"multipleOf,omitempty" protobuf:"bytes,19,opt,name=multipleOf"`
+	Enum                 []JSON                     `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
+	MaxProperties        *int64                     `json:"maxProperties,omitempty" protobuf:"bytes,21,opt,name=maxProperties"`
+	MinProperties        *int64                     `json:"minProperties,omitempty" protobuf:"bytes,22,opt,name=minProperties"`
+	Required             []string                   `json:"required,omitempty" protobuf:"bytes,23,rep,name=required"`
+	Items                *JSONSchemaPropsOrArray    `json:"items,omitempty" protobuf:"bytes,24,opt,name=items"`
+	AllOf                []JSONSchemaProps          `json:"allOf,omitempty" protobuf:"bytes,25,rep,name=allOf"`
+	OneOf                []JSONSchemaProps          `json:"oneOf,omitempty" protobuf:"bytes,26,rep,name=oneOf"`
+	AnyOf                []JSONSchemaProps          `json:"anyOf,omitempty" protobuf:"bytes,27,rep,name=anyOf"`
+	Not                  *JSONSchemaProps           `json:"not,omitempty" protobuf:"bytes,28,opt,name=not"`
+	Properties           map[string]JSONSchemaProps `json:"properties,omitempty" protobuf:"bytes,29,rep,name=properties"`
+	AdditionalProperties *JSONSchemaPropsOrBool     `json:"additionalProperties,omitempty" protobuf:"bytes,30,opt,name=additionalProperties"`
+	PatternProperties    map[string]JSONSchemaProps `json:"patternProperties,omitempty" protobuf:"bytes,31,rep,name=patternProperties"`
+	Dependencies         JSONSchemaDependencies     `json:"dependencies,omitempty" protobuf:"bytes,32,opt,name=dependencies"`
+	AdditionalItems      *JSONSchemaPropsOrBool     `json:"additionalItems,omitempty" protobuf:"bytes,33,opt,name=additionalItems"`
+	Definitions          JSONSchemaDefinitions      `json:"definitions,omitempty" protobuf:"bytes,34,opt,name=definitions"`
+	ExternalDocs         *ExternalDocumentation     `json:"externalDocs,omitempty" protobuf:"bytes,35,opt,name=externalDocs"`
+	Example              *JSON                      `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
+	Nullable             bool                       `json:"nullable,omitempty" protobuf:"bytes,37,opt,name=nullable"`
+
+	// x-kubernetes-preserve-unknown-fields stops the API server
+	// decoding step from pruning fields which are not specified
+	// in the validation schema. This affects fields recursively,
+	// but switches back to normal pruning behaviour if nested
+	// properties or additionalProperties are specified in the schema.
+	// This can either be true or undefined. False is forbidden.
+	XPreserveUnknownFields *bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
+
+	// x-kubernetes-embedded-resource defines that the value is an
+	// embedded Kubernetes runtime.Object, with TypeMeta and
+	// ObjectMeta. The type must be object. It is allowed to further
+	// restrict the embedded object. kind, apiVersion and metadata
+	// are validated automatically. x-kubernetes-preserve-unknown-fields
+	// is allowed to be true, but does not have to be if the object
+	// is fully specified (up to kind, apiVersion, metadata).
+	XEmbeddedResource bool `json:"x-kubernetes-embedded-resource,omitempty" protobuf:"bytes,39,opt,name=xKubernetesEmbeddedResource"`
+
+	// x-kubernetes-int-or-string specifies that this value is
+	// either an integer or a string. If this is true, an empty
+	// type is allowed and type as child of anyOf is permitted
+	// if following one of the following patterns:
+	//
+	// 1) anyOf:
+	//    - type: integer
+	//    - type: string
+	// 2) allOf:
+	//    - anyOf:
+	//      - type: integer
+	//      - type: string
+	//    - ... zero or more
+	XIntOrString bool `json:"x-kubernetes-int-or-string,omitempty" protobuf:"bytes,40,opt,name=xKubernetesIntOrString"`
+
+	// x-kubernetes-list-map-keys annotates an array with the x-kubernetes-list-type `map` by specifying the keys used
+	// as the index of the map.
+	//
+	// This tag MUST only be used on lists that have the "x-kubernetes-list-type"
+	// extension set to "map". Also, the values specified for this attribute must
+	// be a scalar typed field of the child structure (no nesting is supported).
+	//
+	// The properties specified must either be required or have a default value,
+	// to ensure those properties are present for all list items.
+	//
+	// +optional
+	XListMapKeys []string `json:"x-kubernetes-list-map-keys,omitempty" protobuf:"bytes,41,rep,name=xKubernetesListMapKeys"`
+
+	// x-kubernetes-list-type annotates an array to further describe its topology.
+	// This extension must only be used on lists and may have 3 possible values:
+	//
+	// 1) `atomic`: the list is treated as a single entity, like a scalar.
+	//      Atomic lists will be entirely replaced when updated. This extension
+	//      may be used on any type of list (struct, scalar, ...).
+	// 2) `set`:
+	//      Sets are lists that must not have multiple items with the same value. Each
+	//      value must be a scalar, an object with x-kubernetes-map-type `atomic` or an
+	//      array with x-kubernetes-list-type `atomic`.
+	// 3) `map`:
+	//      These lists are like maps in that their elements have a non-index key
+	//      used to identify them. Order is preserved upon merge. The map tag
+	//      must only be used on a list with elements of type object.
+	// Defaults to atomic for arrays.
+	// +optional
+	XListType *string `json:"x-kubernetes-list-type,omitempty" protobuf:"bytes,42,opt,name=xKubernetesListType"`
+
+	// x-kubernetes-map-type annotates an object to further describe its topology.
+	// This extension must only be used when type is object and may have 2 possible values:
+	//
+	// 1) `granular`:
+	//      These maps are actual maps (key-value pairs) and each fields are independent
+	//      from each other (they can each be manipulated by separate actors). This is
+	//      the default behaviour for all maps.
+	// 2) `atomic`: the list is treated as a single entity, like a scalar.
+	//      Atomic maps will be entirely replaced when updated.
+	// +optional
+	XMapType *string `json:"x-kubernetes-map-type,omitempty" protobuf:"bytes,43,opt,name=xKubernetesMapType"`
+}
+
+// JSON represents any valid JSON value.
+// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
+type JSON struct {
+	Raw []byte `protobuf:"bytes,1,opt,name=raw"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSON) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSON) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaURL represents a schema url.
+type JSONSchemaURL string
+
+// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
+// or an array of JSONSchemaProps. Mainly here for serialization purposes.
+type JSONSchemaPropsOrArray struct {
+	Schema      *JSONSchemaProps  `protobuf:"bytes,1,opt,name=schema"`
+	JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
+// Defaults to true for the boolean property.
+type JSONSchemaPropsOrBool struct {
+	Allows bool             `protobuf:"varint,1,opt,name=allows"`
+	Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaDependencies represent a dependencies property.
+type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray
+
+// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
+type JSONSchemaPropsOrStringArray struct {
+	Schema   *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
+	Property []string         `protobuf:"bytes,2,rep,name=property"`
+}
+
+// OpenAPISchemaType is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+//
+// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
+func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
+	// TODO: return actual types when anyOf is supported
+	return nil
+}
+
+// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
+// the OpenAPI spec of this type.
+func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }
+
+// JSONSchemaDefinitions contains the models explicitly defined in this spec.
+type JSONSchemaDefinitions map[string]JSONSchemaProps
+
+// ExternalDocumentation allows referencing an external resource for extended documentation.
+type ExternalDocumentation struct {
+	Description string `json:"description,omitempty" protobuf:"bytes,1,opt,name=description"`
+	URL         string `json:"url,omitempty" protobuf:"bytes,2,opt,name=url"`
+}
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go
index 190a71d..0855489 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types.go
@@ -1,53 +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.
+*/
+
 package v1alpha1
 
 import (
 	camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	openapi "github.com/go-openapi/spec"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
+const (
+	AnnotationIcon = "camel.apache.org/icon"
+)
+
 // KameletSpec defines the desired state of Kamelet
 type KameletSpec struct {
-	Info          KameletInfo         `json:"info,omitempty"`
-	Parameters    []KameletParameter  `json:"parameters,omitempty"`
-	Authorization AuthorizationSpec   `json:"authorization,omitempty"`
-	Sources       *camelv1.SourceSpec `json:"sources,omitempty"`
-	Flow          *camelv1.Flow       `json:"flow,omitempty"`
-	Consumes      *EventType          `json:"consumes,omitempty"`
-	Produces      *EventType          `json:"produces,omitempty"`
-	Dependencies  []string            `json:"dependencies,omitempty"`
-}
-
-type EventType struct {
-	Type   string      `json:"type,omitempty"`
-	Schema *DataSchema `json:"schema,omitempty"`
+	Definition    JSONSchemaProps             `json:"definition,omitempty"`
+	Sources       *camelv1.SourceSpec         `json:"sources,omitempty"`
+	Flow          *camelv1.Flow               `json:"flow,omitempty"`
+	Authorization AuthorizationSpec           `json:"authorization,omitempty"`
+	Types         map[EventSlot]EventTypeSpec `json:"types,omitempty"`
+	Dependencies  []string                    `json:"dependencies,omitempty"`
 }
 
-type DataSchema struct {
-	Ref     *corev1.ObjectReference `json:"ref,omitempty"`
-	Content *openapi.Schema         `json:"schema,omitempty"`
+type EventTypeSpec struct {
+	MediaType string           `json:"mediaType,omitempty"`
+	Schema    *JSONSchemaProps `json:"schema,omitempty"`
 }
 
-type KameletInfo struct {
-	DisplayName string      `json:"displayName,omitempty"`
-	Description string      `json:"description,omitempty"`
-	Group       string      `json:"group,omitempty"`
-	Icon        KameletIcon `json:"icon,omitempty"`
-}
-
-type KameletIcon struct {
-	Data      string `json:"data,omitempty"`
-	MediaType string `json:"mediaType,omitempty"`
-}
+type EventSlot string
 
-type KameletParameter struct {
-	Name        string            `json:"name,omitempty"`
-	Required    bool              `json:"required,omitempty"`
-	Description string            `json:"description,omitempty"`
-	Annotations map[string]string `json:"annotations,omitempty"`
-	Schema      *openapi.Schema   `json:"schema,omitempty"`
-}
+const (
+	EventSlotIn    EventSlot = "in"
+	EventSlotOut   EventSlot = "out"
+	EventSlotError EventSlot = "error"
+)
 
 // AuthorizationSpec is TODO (oauth information)
 type AuthorizationSpec struct {
diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
index eb18093..b4f25c1 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_types_support.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go
@@ -1,3 +1,20 @@
+/*
+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 (
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 8c7d0d7..b81d3ca 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -5,16 +5,371 @@
 package v1alpha1
 
 import (
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthorizationSpec) DeepCopyInto(out *AuthorizationSpec) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationSpec.
+func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthorizationSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDocumentation.
+func (in *ExternalDocumentation) DeepCopy() *ExternalDocumentation {
+	if in == nil {
+		return nil
+	}
+	out := new(ExternalDocumentation)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSON) DeepCopyInto(out *JSON) {
+	*out = *in
+	if in.Raw != nil {
+		in, out := &in.Raw, &out.Raw
+		*out = make([]byte, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSON.
+func (in *JSON) DeepCopy() *JSON {
+	if in == nil {
+		return nil
+	}
+	out := new(JSON)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in JSONSchemaDefinitions) DeepCopyInto(out *JSONSchemaDefinitions) {
+	{
+		in := &in
+		*out = make(JSONSchemaDefinitions, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+		return
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDefinitions.
+func (in JSONSchemaDefinitions) DeepCopy() JSONSchemaDefinitions {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaDefinitions)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in JSONSchemaDependencies) DeepCopyInto(out *JSONSchemaDependencies) {
+	{
+		in := &in
+		*out = make(JSONSchemaDependencies, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+		return
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDependencies.
+func (in JSONSchemaDependencies) DeepCopy() JSONSchemaDependencies {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaDependencies)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
+	*out = *in
+	if in.Ref != nil {
+		in, out := &in.Ref, &out.Ref
+		*out = new(string)
+		**out = **in
+	}
+	if in.Default != nil {
+		in, out := &in.Default, &out.Default
+		*out = new(JSON)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Maximum != nil {
+		in, out := &in.Maximum, &out.Maximum
+		*out = new(float64)
+		**out = **in
+	}
+	if in.Minimum != nil {
+		in, out := &in.Minimum, &out.Minimum
+		*out = new(float64)
+		**out = **in
+	}
+	if in.MaxLength != nil {
+		in, out := &in.MaxLength, &out.MaxLength
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinLength != nil {
+		in, out := &in.MinLength, &out.MinLength
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MaxItems != nil {
+		in, out := &in.MaxItems, &out.MaxItems
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinItems != nil {
+		in, out := &in.MinItems, &out.MinItems
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MultipleOf != nil {
+		in, out := &in.MultipleOf, &out.MultipleOf
+		*out = new(float64)
+		**out = **in
+	}
+	if in.Enum != nil {
+		in, out := &in.Enum, &out.Enum
+		*out = make([]JSON, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.MaxProperties != nil {
+		in, out := &in.MaxProperties, &out.MaxProperties
+		*out = new(int64)
+		**out = **in
+	}
+	if in.MinProperties != nil {
+		in, out := &in.MinProperties, &out.MinProperties
+		*out = new(int64)
+		**out = **in
+	}
+	if in.Required != nil {
+		in, out := &in.Required, &out.Required
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = new(JSONSchemaPropsOrArray)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.AllOf != nil {
+		in, out := &in.AllOf, &out.AllOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.OneOf != nil {
+		in, out := &in.OneOf, &out.OneOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.AnyOf != nil {
+		in, out := &in.AnyOf, &out.AnyOf
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Not != nil {
+		in, out := &in.Not, &out.Not
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Properties != nil {
+		in, out := &in.Properties, &out.Properties
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.AdditionalProperties != nil {
+		in, out := &in.AdditionalProperties, &out.AdditionalProperties
+		*out = new(JSONSchemaPropsOrBool)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.PatternProperties != nil {
+		in, out := &in.PatternProperties, &out.PatternProperties
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.Dependencies != nil {
+		in, out := &in.Dependencies, &out.Dependencies
+		*out = make(JSONSchemaDependencies, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.AdditionalItems != nil {
+		in, out := &in.AdditionalItems, &out.AdditionalItems
+		*out = new(JSONSchemaPropsOrBool)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Definitions != nil {
+		in, out := &in.Definitions, &out.Definitions
+		*out = make(JSONSchemaDefinitions, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.ExternalDocs != nil {
+		in, out := &in.ExternalDocs, &out.ExternalDocs
+		*out = new(ExternalDocumentation)
+		**out = **in
+	}
+	if in.Example != nil {
+		in, out := &in.Example, &out.Example
+		*out = new(JSON)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.XPreserveUnknownFields != nil {
+		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
+		*out = new(bool)
+		**out = **in
+	}
+	if in.XListMapKeys != nil {
+		in, out := &in.XListMapKeys, &out.XListMapKeys
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.XListType != nil {
+		in, out := &in.XListType, &out.XListType
+		*out = new(string)
+		**out = **in
+	}
+	if in.XMapType != nil {
+		in, out := &in.XMapType, &out.XMapType
+		*out = new(string)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaProps.
+func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaProps)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrArray) DeepCopyInto(out *JSONSchemaPropsOrArray) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.JSONSchemas != nil {
+		in, out := &in.JSONSchemas, &out.JSONSchemas
+		*out = make([]JSONSchemaProps, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrArray.
+func (in *JSONSchemaPropsOrArray) DeepCopy() *JSONSchemaPropsOrArray {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrArray)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrBool) DeepCopyInto(out *JSONSchemaPropsOrBool) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrBool.
+func (in *JSONSchemaPropsOrBool) DeepCopy() *JSONSchemaPropsOrBool {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrBool)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JSONSchemaPropsOrStringArray) DeepCopyInto(out *JSONSchemaPropsOrStringArray) {
+	*out = *in
+	if in.Schema != nil {
+		in, out := &in.Schema, &out.Schema
+		*out = new(JSONSchemaProps)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Property != nil {
+		in, out := &in.Property, &out.Property
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrStringArray.
+func (in *JSONSchemaPropsOrStringArray) DeepCopy() *JSONSchemaPropsOrStringArray {
+	if in == nil {
+		return nil
+	}
+	out := new(JSONSchemaPropsOrStringArray)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Kamelet) DeepCopyInto(out *Kamelet) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	out.Spec = in.Spec
-	out.Status = in.Status
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
 	return
 }
 
@@ -37,6 +392,24 @@ func (in *Kamelet) DeepCopyObject() runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KameletCondition) DeepCopyInto(out *KameletCondition) {
+	*out = *in
+	in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
+	in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletCondition.
+func (in *KameletCondition) DeepCopy() *KameletCondition {
+	if in == nil {
+		return nil
+	}
+	out := new(KameletCondition)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletList) DeepCopyInto(out *KameletList) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
@@ -72,6 +445,29 @@ func (in *KameletList) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletSpec) DeepCopyInto(out *KameletSpec) {
 	*out = *in
+	in.Definition.DeepCopyInto(&out.Definition)
+	if in.Sources != nil {
+		in, out := &in.Sources, &out.Sources
+		*out = new(v1.SourceSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Flow != nil {
+		in, out := &in.Flow, &out.Flow
+		*out = (*in).DeepCopy()
+	}
+	out.Authorization = in.Authorization
+	if in.Types != nil {
+		in, out := &in.Types, &out.Types
+		*out = make(map[string]JSONSchemaProps, len(*in))
+		for key, val := range *in {
+			(*out)[key] = *val.DeepCopy()
+		}
+	}
+	if in.Dependencies != nil {
+		in, out := &in.Dependencies, &out.Dependencies
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	return
 }
 
@@ -88,6 +484,13 @@ func (in *KameletSpec) DeepCopy() *KameletSpec {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KameletStatus) DeepCopyInto(out *KameletStatus) {
 	*out = *in
+	if in.Conditions != nil {
+		in, out := &in.Conditions, &out.Conditions
+		*out = make([]KameletCondition, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
 	return
 }
 
diff --git a/pkg/controller/add_kamelet.go b/pkg/controller/add_kamelet.go
new file mode 100644
index 0000000..7818bcd
--- /dev/null
+++ b/pkg/controller/add_kamelet.go
@@ -0,0 +1,26 @@
+/*
+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 controller
+
+import (
+	"github.com/apache/camel-k/pkg/controller/kamelet"
+)
+
+func init() {
+	// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
+	AddToManagerFuncs = append(AddToManagerFuncs, kamelet.Add)
+}