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 4bea9af710a7d05869e6c0e1baa660b62ad34bb4 Author: nicolaferraro <[email protected]> AuthorDate: Tue Aug 11 16:37:23 2020 +0200 Fix #1574: implement changes in source loading --- deploy/resources.go | 12 +- deploy/traits.yaml | 17 +++ docs/modules/ROOT/nav.adoc | 1 + docs/modules/traits/pages/kamelets.adoc | 39 +++++ pkg/apis/camel/v1/integration_types.go | 6 +- pkg/apis/camel/v1/zz_generated.deepcopy.go | 5 + pkg/apis/camel/v1alpha1/jsonschema_types.go | 8 +- pkg/apis/camel/v1alpha1/kamelet_types.go | 14 +- pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 51 ++++++- pkg/controller/kamelet/common.go | 48 ++++++ pkg/controller/kamelet/initialize.go | 4 +- pkg/controller/kamelet/monitor.go | 3 +- pkg/trait/container.go | 9 +- pkg/trait/kamelets.go | 44 ++++-- pkg/trait/kamelets_test.go | 14 +- pkg/trait/knative_service_test.go | 10 +- pkg/trait/trait_test.go | 8 +- pkg/trait/trait_types.go | 183 ++++++----------------- 18 files changed, 284 insertions(+), 192 deletions(-) diff --git a/deploy/resources.go b/deploy/resources.go index 0741e84..673756d 100644 --- a/deploy/resources.go +++ b/deploy/resources.go @@ -144,6 +144,13 @@ var assets = func() http.FileSystem { compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3a\x4f\x8f\xe2\x38\xf6\xf7\x7c\x8a\xa7\xe2\xd0\x33\x52\x01\xbf\x9e\xb9\xfc\xc4\x9e\x58\xba\x4b\xcb\x76\x37\x55\x02\x7a\x46\x73\x34\xce\x23\x78\xcb\xb1\xb3\xb6\x03\x5d\xbb\xda\xef\xbe\x7a\x76\x12\x92\x90\x50\x14\xd5\xad\x95\x46\x95\x1b\xf1\xfb\xff\xdf\x2f\x0c\x60\xf8\xfd\x9e\x68\x00\x9f\x05\x47\x65\x31\x06\xa7\xc1\xed\x10\xa6\x19\xe3\x3b\x84\x95\xde\xba\x03\x33\x08\x77\x3a\x57\x31\x73\x42\x2b\xf8\x69\xba\xba\xfb\x [...] }, + "/crd-kamelet.yaml": &vfsgen۰CompressedFileInfo{ + name: "crd-kamelet.yaml", + modTime: time.Time{}, + uncompressedSize: 1498, + + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x54\xc1\x6e\xe3\x36\x10\xbd\xeb\x2b\x1e\xac\xcb\x2e\x10\xcb\x4d\x4f\x85\x7a\x72\xbd\x09\xea\x26\x90\x83\xc8\xdb\xc5\x1e\xc7\xd2\x58\x1a\x98\x22\x59\x92\xb2\x63\x14\xfd\xf7\x82\x92\x1c\x3b\x68\x8f\xab\x93\xfd\x66\x38\xf3\xde\xbc\x21\x53\xcc\x7f\xdc\x97\xa4\x78\x96\x8a\xb5\xe7\x1a\xc1\x20\xb4\x8c\xa5\xa5\xaa\x65\x94\x66\x1f\x4e\xe4\x18\x8f\xa6\xd7\x35\x05\x31\x1a\x9f\x96\xe5\xe3\x67\xf4\xba\x66\x07\xa3\x19\xc6\xa1\x [...] + }, "/operator-deployment.yaml": &vfsgen۰CompressedFileInfo{ name: "operator-deployment.yaml", modTime: time.Time{}, @@ -354,9 +361,9 @@ var assets = func() http.FileSystem { "/traits.yaml": &vfsgen۰CompressedFileInfo{ name: "traits.yaml", modTime: time.Time{}, - uncompressedSize: 32177, + uncompressedSize: 32786, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1b\x37\x92\xf0\xf7\xfc\x0a\x94\x9e\xa7\x4a\xa2\x8a\x1c\xc9\xd9\xca\x26\xab\xbb\x5c\x4a\xeb\x38\xbb\x72\x62\x5b\x67\x39\xc9\x5d\xe5\xb6\x96\xe0\x4c\x93\x84\x85\x01\x66\x01\x0c\x65\xe6\xea\xfe\xfb\x55\x37\x5e\x06\x33\x1c\x49\x94\x63\xa5\xb4\x55\x57\xf9\x10\x93\x9a\x69\x34\x1a\xfd\xfe\x02\x3a\xc3\x85\xb3\x67\x9f\xcd\x98\xe2\x35\x9c\x31\xbe\x5c\x0a\x25\xdc\xf6\x33\xc6\x1a\xc9\xdd\x52\x9b\xfa\x8c\x2d\xb9\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1b\x37\x92\xf0\xf7\xfc\x0a\x94\x9e\xa7\x4a\xa2\x8a\x1c\xc9\xd9\xca\x26\xab\xbb\x5c\x4a\xeb\x38\xbb\x72\x62\x5b\x67\x39\xc9\x5d\xe5\xb6\x96\xe0\x4c\x93\x84\x85\x01\x66\x01\x0c\x65\xe6\xea\xfe\xfb\x55\x37\x5e\x06\x33\x1c\x49\x94\x63\xa5\xb4\x55\x57\xf9\x10\x93\x9a\x69\x34\x1a\xfd\xfe\x02\x3a\xc3\x85\xb3\x67\x9f\xcd\x98\xe2\x35\x9c\x31\xbe\x5c\x0a\x25\xdc\xf6\x33\xc6\x1a\xc9\xdd\x52\x9b\xfa\x8c\x2d\xb9\x [...] }, "/user-cluster-role.yaml": &vfsgen۰CompressedFileInfo{ name: "user-cluster-role.yaml", @@ -380,6 +387,7 @@ var assets = func() http.FileSystem { fs["/crd-integration-kit.yaml"].(os.FileInfo), fs["/crd-integration-platform.yaml"].(os.FileInfo), fs["/crd-integration.yaml"].(os.FileInfo), + fs["/crd-kamelet.yaml"].(os.FileInfo), fs["/operator-deployment.yaml"].(os.FileInfo), fs["/operator-role-binding-events.yaml"].(os.FileInfo), fs["/operator-role-binding-knative.yaml"].(os.FileInfo), diff --git a/deploy/traits.yaml b/deploy/traits.yaml index 070d61c..c2d85f0 100755 --- a/deploy/traits.yaml +++ b/deploy/traits.yaml @@ -319,6 +319,23 @@ traits: - name: options type: '[]string' description: A list of JVM options +- name: kamelets + platform: true + profiles: + - Kubernetes + - Knative + - OpenShift + description: The kamelets trait is a platform trait used to inject Kamelets into the integration runtime. + properties: + - name: enabled + type: bool + description: Can be used to enable or disable a trait. All traits share this common property. + - name: auto + type: bool + description: Automatically inject all referenced Kamelets and their default configuration (enabled by default) + - name: list + type: string + description: Comma separated list of Kamelet names to load into the current integration - name: knative-service platform: false profiles: diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 039d5c3..7c00b89 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -37,6 +37,7 @@ ** xref:traits:istio.adoc[Istio] ** xref:traits:jolokia.adoc[Jolokia] ** xref:traits:jvm.adoc[Jvm] +** xref:traits:kamelets.adoc[Kamelets] ** xref:traits:knative-service.adoc[Knative Service] ** xref:traits:knative.adoc[Knative] ** xref:traits:master.adoc[Master] diff --git a/docs/modules/traits/pages/kamelets.adoc b/docs/modules/traits/pages/kamelets.adoc new file mode 100755 index 0000000..7409709 --- /dev/null +++ b/docs/modules/traits/pages/kamelets.adoc @@ -0,0 +1,39 @@ += Kamelets Trait + +// Start of autogenerated code - DO NOT EDIT! (description) +The kamelets trait is a platform trait used to inject Kamelets into the integration runtime. + + +This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. + +WARNING: The kamelets 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: +``` +kamel run --trait kamelets.[key]=[value] --trait kamelets.[key2]=[value2] integration.groovy +``` +The following configuration options are available: + +[cols="2,1,5a"] +|=== +|Property | Type | Description + +| kamelets.enabled +| bool +| Can be used to enable or disable a trait. All traits share this common property. + +| kamelets.auto +| bool +| Automatically inject all referenced Kamelets and their default configuration (enabled by default) + +| kamelets.list +| string +| Comma separated list of Kamelet names to load into the current integration + +|=== + +// End of autogenerated code - DO NOT EDIT! (configuration) diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go index 7e985a2..47aeb44 100644 --- a/pkg/apis/camel/v1/integration_types.go +++ b/pkg/apis/camel/v1/integration_types.go @@ -127,13 +127,15 @@ type SourceSpec struct { Interceptors []string `json:"interceptors,omitempty"` // Type defines the kind of source described by this object Type SourceType `json:"type,omitempty"` + // List of property names defined in the source (e.g. if type is "template") + PropertyNames []string `json:"property-names,omitempty"` } type SourceType string const ( - SourceTypeDefault SourceType = "" - SourceTypeKamelet SourceType = "kamelet" + SourceTypeDefault SourceType = "" + SourceTypeTemplate SourceType = "template" ) // Language -- diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go index d48aa41..534a75d 100644 --- a/pkg/apis/camel/v1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go @@ -1312,6 +1312,11 @@ func (in *SourceSpec) DeepCopyInto(out *SourceSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.PropertyNames != nil { + in, out := &in.PropertyNames, &out.PropertyNames + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/apis/camel/v1alpha1/jsonschema_types.go b/pkg/apis/camel/v1alpha1/jsonschema_types.go index 6ebdf1e..a66b131 100644 --- a/pkg/apis/camel/v1alpha1/jsonschema_types.go +++ b/pkg/apis/camel/v1alpha1/jsonschema_types.go @@ -19,6 +19,8 @@ limitations under the License. package v1alpha1 +import "encoding/json" + // 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"` @@ -59,7 +61,7 @@ type JSONSchemaProps struct { // 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"` + Default *json.RawMessage `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"` @@ -71,7 +73,7 @@ type JSONSchemaProps struct { 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"` + Enum []*json.RawMessage `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"` @@ -87,7 +89,7 @@ type JSONSchemaProps struct { 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"` + Example *json.RawMessage `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 diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go index 34594b2..81557a1 100644 --- a/pkg/apis/camel/v1alpha1/kamelet_types.go +++ b/pkg/apis/camel/v1alpha1/kamelet_types.go @@ -58,6 +58,12 @@ type AuthorizationSpec struct { type KameletStatus struct { Phase KameletPhase `json:"phase,omitempty"` Conditions []KameletCondition `json:"conditions,omitempty"` + Properties []KameletProperty `json:"properties,omitempty"` +} + +type KameletProperty struct { + Name string `json:"name,omitempty"` + Default string `json:"default,omitempty"` } // KameletCondition describes the state of a resource at a certain point. @@ -95,11 +101,13 @@ const ( KameletPhaseReady KameletPhase = "Ready" ) -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - // Kamelet is the Schema for the kamelets API +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +// +genclient +// +kubebuilder:resource:path=kamelets,scope=Namespaced,shortName=kl,categories=kamel;camel // +kubebuilder:subresource:status -// +kubebuilder:resource:path=kamelets,scope=Namespaced +// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`,description="The Kamelet phase" type Kamelet struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go index e6c991c..2014759 100644 --- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go @@ -5,6 +5,8 @@ package v1alpha1 import ( + json "encoding/json" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -137,8 +139,12 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) { } if in.Default != nil { in, out := &in.Default, &out.Default - *out = new(JSON) - (*in).DeepCopyInto(*out) + *out = new(json.RawMessage) + if **in != nil { + in, out := *in, *out + *out = make([]byte, len(*in)) + copy(*out, *in) + } } if in.Maximum != nil { in, out := &in.Maximum, &out.Maximum @@ -177,9 +183,17 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) { } if in.Enum != nil { in, out := &in.Enum, &out.Enum - *out = make([]JSON, len(*in)) + *out = make([]*json.RawMessage, len(*in)) for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(json.RawMessage) + if **in != nil { + in, out := *in, *out + *out = make([]byte, len(*in)) + copy(*out, *in) + } + } } } if in.MaxProperties != nil { @@ -273,8 +287,12 @@ func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) { } if in.Example != nil { in, out := &in.Example, &out.Example - *out = new(JSON) - (*in).DeepCopyInto(*out) + *out = new(json.RawMessage) + if **in != nil { + in, out := *in, *out + *out = make([]byte, len(*in)) + copy(*out, *in) + } } if in.XPreserveUnknownFields != nil { in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields @@ -464,6 +482,22 @@ 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 *KameletProperty) DeepCopyInto(out *KameletProperty) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KameletProperty. +func (in *KameletProperty) DeepCopy() *KameletProperty { + if in == nil { + return nil + } + out := new(KameletProperty) + in.DeepCopyInto(out) + return out +} + +// 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) @@ -515,6 +549,11 @@ func (in *KameletStatus) DeepCopyInto(out *KameletStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Properties != nil { + in, out := &in.Properties, &out.Properties + *out = make([]KameletProperty, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/controller/kamelet/common.go b/pkg/controller/kamelet/common.go new file mode 100644 index 0000000..d95b27a --- /dev/null +++ b/pkg/controller/kamelet/common.go @@ -0,0 +1,48 @@ +package kamelet + +import ( + "encoding/json" + "fmt" + "sort" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/pkg/errors" +) + +func updateStatus(kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) { + target := kamelet.DeepCopy() + target.Status.Phase = v1alpha1.KameletPhaseReady + if err := recomputeProperties(target); err != nil { + return nil, err + } + return target, nil +} + +func recomputeProperties(kamelet *v1alpha1.Kamelet) error { + kamelet.Status.Properties = make([]v1alpha1.KameletProperty, 0, len(kamelet.Spec.Definition.Properties)) + propSet := make(map[string]bool) + for k, v := range kamelet.Spec.Definition.Properties { + if propSet[k] { + continue + } + propSet[k] = true + defValue := "" + if v.Default != nil { + var val interface{} + if err := json.Unmarshal(*v.Default, &val); err != nil { + return errors.Wrapf(err, "cannot decode default value for property %q", k) + } + defValue = fmt.Sprintf("%v", val) + } + kamelet.Status.Properties = append(kamelet.Status.Properties, v1alpha1.KameletProperty{ + Name: k, + Default: defValue, + }) + } + sort.SliceStable(kamelet.Status.Properties, func(i, j int) bool { + pi := kamelet.Status.Properties[i].Name + pj := kamelet.Status.Properties[j].Name + return pi < pj + }) + return nil +} diff --git a/pkg/controller/kamelet/initialize.go b/pkg/controller/kamelet/initialize.go index 0b3f0aa..eeae301 100644 --- a/pkg/controller/kamelet/initialize.go +++ b/pkg/controller/kamelet/initialize.go @@ -41,7 +41,5 @@ func (action *initializeAction) CanHandle(kamelet *v1alpha1.Kamelet) bool { } func (action *initializeAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) { - target := kamelet.DeepCopy() - target.Status.Phase = v1alpha1.KameletPhaseReady - return target, nil + return updateStatus(kamelet) } diff --git a/pkg/controller/kamelet/monitor.go b/pkg/controller/kamelet/monitor.go index 49935d2..99e5224 100644 --- a/pkg/controller/kamelet/monitor.go +++ b/pkg/controller/kamelet/monitor.go @@ -41,6 +41,5 @@ func (action *monitorAction) CanHandle(kamelet *v1alpha1.Kamelet) bool { } func (action *monitorAction) Handle(ctx context.Context, kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) { - // Doing nothing for now - return kamelet, nil + return updateStatus(kamelet) } diff --git a/pkg/trait/container.go b/pkg/trait/container.go index 9c19e5e..485b302 100644 --- a/pkg/trait/container.go +++ b/pkg/trait/container.go @@ -21,19 +21,16 @@ import ( "fmt" "sort" "strconv" - "strings" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/apache/camel-k/pkg/util" + "github.com/apache/camel-k/pkg/util/envvar" appsv1 "k8s.io/api/apps/v1" "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" - serving "knative.dev/serving/pkg/apis/serving/v1" - - v1 "github.com/apache/camel-k/pkg/apis/camel/v1" - "github.com/apache/camel-k/pkg/util/envvar" ) const ( @@ -195,8 +192,6 @@ func (t *containerTrait) configureContainer(e *Environment) error { envvar.SetVal(&container.Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties") envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d") - // Configure sources - envvar.SetVal(&container.Env, "CAMEL_K_ROUTES", strings.Join(e.ComputeSourcesURI(), ",")) e.AddSourcesProperties() t.configureResources(e, &container) diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go index d1b3bef..05f734f 100644 --- a/pkg/trait/kamelets.go +++ b/pkg/trait/kamelets.go @@ -88,7 +88,7 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) { return false, nil } - if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) { return false, nil } @@ -114,11 +114,16 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, error) { } func (t *kameletsTrait) Apply(e *Environment) error { - if err := t.addKamelets(e); err != nil { - return err - } - if err := t.addConfigurationSecrets(e); err != nil { - return err + + if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + if err := t.addKamelets(e); err != nil { + return err + } + if err := t.addConfigurationSecrets(e); err != nil { + return err + } + } else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) { + return t.configureApplicationProperties(e) } return nil } @@ -150,6 +155,27 @@ func (t *kameletsTrait) addKamelets(e *Environment) error { return nil } +func (t *kameletsTrait) configureApplicationProperties(e *Environment) error { + for _, k := range t.getKameletKeys() { + var kamelet v1alpha1.Kamelet + key := client.ObjectKey{ + Namespace: e.Integration.Namespace, + Name: k, + } + if err := t.Client.Get(t.Ctx, key, &kamelet); err != nil { + return err + } + + // Configuring defaults from Kamelet + for _, prop := range kamelet.Status.Properties { + if prop.Default != "" { + e.ApplicationProperties[fmt.Sprintf("camel.kamelet.%s.%s", kamelet.Name, prop.Name)] = prop.Default + } + } + } + return nil +} + func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kamelet) error { sources := make([]v1.SourceSpec, 0) @@ -165,7 +191,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame Content: string(flowData), }, Language: v1.LanguageYaml, - Type: v1.SourceTypeKamelet, + Type: v1.SourceTypeTemplate, } flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name)) if err != nil { @@ -184,7 +210,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet v1alpha1.Kame kameletCounter := 0 for _, source := range sources { - if source.Type == v1.SourceTypeKamelet { + if source.Type == v1.SourceTypeTemplate { kameletCounter++ } replaced := false @@ -279,7 +305,7 @@ func (t *kameletsTrait) getConfigurationKeys() []configurationKey { } func integrationSourceFromKameletSource(e *Environment, kamelet v1alpha1.Kamelet, source v1.SourceSpec, name string) (v1.SourceSpec, error) { - if source.Type == v1.SourceTypeKamelet { + if source.Type == v1.SourceTypeTemplate { // Kamelets must be named "<kamelet-name>.extension" language := source.InferLanguage() source.Name = fmt.Sprintf("%s.%s", kamelet.Name, string(language)) diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go index 4f37b1d..e72ad78 100644 --- a/pkg/trait/kamelets_test.go +++ b/pkg/trait/kamelets_test.go @@ -115,7 +115,7 @@ func TestKameletLookup(t *testing.T) { assert.Len(t, environment.Integration.Status.GeneratedSources, 1) source := environment.Integration.Status.GeneratedSources[0] assert.Equal(t, "timer.yaml", source.Name) - assert.Equal(t, "kamelet", string(source.Type)) + assert.Equal(t, "template", string(source.Type)) assert.Equal(t, []string{"camel:log", "camel:timer"}, environment.Integration.Status.Dependencies) } @@ -165,7 +165,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) { flowSource := environment.Integration.Status.GeneratedSources[0] assert.Equal(t, "timer.yaml", flowSource.Name) - assert.Equal(t, "kamelet", string(flowSource.Type)) + assert.Equal(t, "template", string(flowSource.Type)) assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef) assert.Equal(t, "content", flowSource.ContentKey) @@ -194,7 +194,7 @@ func TestNonYAMLKameletLookup(t *testing.T) { Name: "mykamelet.groovy", Content: `from("timer").to("log:info")`, }, - Type: v1.SourceTypeKamelet, + Type: v1.SourceTypeTemplate, }, }, }, @@ -215,7 +215,7 @@ func TestNonYAMLKameletLookup(t *testing.T) { assert.Len(t, environment.Integration.Status.GeneratedSources, 1) source := environment.Integration.Status.GeneratedSources[0] assert.Equal(t, "timer.groovy", source.Name) - assert.Equal(t, "kamelet", string(source.Type)) + assert.Equal(t, "template", string(source.Type)) } func TestErrorMultipleKameletSources(t *testing.T) { @@ -236,7 +236,7 @@ func TestErrorMultipleKameletSources(t *testing.T) { Name: "mykamelet.groovy", Content: `from("timer").to("log:info")`, }, - Type: v1.SourceTypeKamelet, + Type: v1.SourceTypeTemplate, }, }, Flow: marshalOrFail(map[string]interface{}{ @@ -333,13 +333,13 @@ func TestMultipleKamelets(t *testing.T) { flowSource2 := environment.Integration.Status.GeneratedSources[0] assert.Equal(t, "logger.yaml", flowSource2.Name) - assert.Equal(t, "kamelet", string(flowSource2.Type)) + assert.Equal(t, "template", string(flowSource2.Type)) assert.Equal(t, "it-kamelet-logger-flow", flowSource2.ContentRef) assert.Equal(t, "content", flowSource2.ContentKey) flowSource := environment.Integration.Status.GeneratedSources[1] assert.Equal(t, "timer.yaml", flowSource.Name) - assert.Equal(t, "kamelet", string(flowSource.Type)) + assert.Equal(t, "template", string(flowSource.Type)) assert.Equal(t, "it-kamelet-timer-flow", flowSource.ContentRef) assert.Equal(t, "content", flowSource.ContentKey) diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go index 9406d32..731eec9 100644 --- a/pkg/trait/knative_service_test.go +++ b/pkg/trait/knative_service_test.go @@ -118,7 +118,7 @@ func TestKnativeService(t *testing.T) { assert.NotEmpty(t, environment.ExecutedTraits) assert.NotNil(t, environment.GetTrait("knative")) assert.NotNil(t, envvar.Get(environment.EnvVars, "CAMEL_KNATIVE_CONFIGURATION")) - assert.Equal(t, 4, environment.Resources.Size()) + assert.Equal(t, 5, environment.Resources.Size()) s := environment.Resources.GetKnativeService(func(service *serving.Service) bool { return service.Name == KnativeServiceTestName @@ -128,8 +128,8 @@ func TestKnativeService(t *testing.T) { spec := s.Spec.ConfigurationSpec.Template.Spec - assert.Len(t, spec.Containers[0].VolumeMounts, 5) - assert.Len(t, spec.Volumes, 5) + assert.Len(t, spec.Containers[0].VolumeMounts, 6) + assert.Len(t, spec.Volumes, 6) assert.Condition(t, func() bool { for _, v := range spec.Containers[0].VolumeMounts { @@ -172,7 +172,9 @@ func TestKnativeService(t *testing.T) { } }) - test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_ROUTES", "file:/etc/camel/sources/i-source-000/routes.js?language=js&compression=true") + assert.Equal(t, "file:/etc/camel/sources/i-source-000/routes.js", environment.ApplicationProperties["camel.k.sources[0].location"]) + assert.Equal(t, "js", environment.ApplicationProperties["camel.k.sources[0].language"]) + assert.Equal(t, "true", environment.ApplicationProperties["camel.k.sources[0].compression"]) test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF", "/etc/camel/conf/application.properties") test.EnvVarHasValue(t, spec.Containers[0].Env, "CAMEL_K_CONF_D", "/etc/camel/conf.d") } diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go index bcf3519..d936c56 100644 --- a/pkg/trait/trait_test.go +++ b/pkg/trait/trait_test.go @@ -49,7 +49,7 @@ func TestOpenShiftTraits(t *testing.T) { assert.Nil(t, env.GetTrait("service")) assert.Nil(t, env.GetTrait("route")) assert.NotNil(t, env.GetTrait("owner")) - assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { + assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { return cm.Labels["camel.apache.org/properties.type"] != "" })) assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool { @@ -64,7 +64,7 @@ func TestOpenShiftTraitsWithWeb(t *testing.T) { assert.NotNil(t, env.GetTrait("service")) assert.NotNil(t, env.GetTrait("route")) assert.NotNil(t, env.GetTrait("owner")) - assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { + assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { return cm.Labels["camel.apache.org/properties.type"] != "" })) assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool { @@ -114,7 +114,7 @@ func TestKubernetesTraits(t *testing.T) { assert.Nil(t, env.GetTrait("service")) assert.Nil(t, env.GetTrait("route")) assert.NotNil(t, env.GetTrait("owner")) - assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { + assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { return cm.Labels["camel.apache.org/properties.type"] != "" })) assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool { @@ -129,7 +129,7 @@ func TestKubernetesTraitsWithWeb(t *testing.T) { assert.NotNil(t, env.GetTrait("service")) assert.Nil(t, env.GetTrait("route")) assert.NotNil(t, env.GetTrait("owner")) - assert.Nil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { + assert.NotNil(t, res.GetConfigMap(func(cm *corev1.ConfigMap) bool { return cm.Labels["camel.apache.org/properties.type"] != "" })) assert.NotNil(t, res.GetDeployment(func(deployment *appsv1.Deployment) bool { diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index c397c2f..3d38531 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -54,9 +54,6 @@ var ( // SourcesMountPath -- SourcesMountPath = path.Join(BasePath, "sources") - // KameletsMountPath -- - KameletsMountPath = path.Join(BasePath, "kamelets.d") - // ResourcesMountPath -- ResourcesMountPath = path.Join(BasePath, "resources") @@ -478,34 +475,43 @@ func (e *Environment) ComputeConfigMaps() []runtime.Object { return maps } -// ComputeSourcesURI -- -func (e *Environment) ComputeSourcesURI() []string { - sources := e.Integration.Sources() - paths := make([]string, 0, len(sources)) - - for i, s := range sources { - if s.Type == v1.SourceTypeKamelet { - // Kamelet information is added to application.properties - continue - } +// AddSourcesProperties -- +func (e *Environment) AddSourcesProperties() { + if e.ApplicationProperties == nil { + e.ApplicationProperties = make(map[string]string) + } + for i, s := range e.Integration.Sources() { root := path.Join(SourcesMountPath, fmt.Sprintf("i-source-%03d", i)) srcName := strings.TrimPrefix(s.Name, "/") src := path.Join(root, srcName) src = "file:" + src - interceptors := make([]string, 0, len(s.Interceptors)) + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].location", i)] = src - params := make([]string, 0) + simpleName := srcName + if strings.Contains(srcName, ".") { + simpleName = srcName[0:strings.Index(srcName, ".")] + } + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].name", i)] = simpleName + + for pid, p := range s.PropertyNames { + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].property-names[%d]", i, pid)] = p + } + + if s.Type != "" { + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].type", i)] = string(s.Type) + } if s.InferLanguage() != "" { - params = append(params, "language="+string(s.InferLanguage())) + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].language", i)] = string(s.InferLanguage()) } if s.Loader != "" { - params = append(params, "loader="+s.Loader) + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].loader", i)] = string(s.Loader) } if s.Compression { - params = append(params, "compression=true") + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compression", i)] = "true" } + interceptors := make([]string, 0, len(s.Interceptors)) if s.Interceptors != nil { interceptors = append(interceptors, s.Interceptors...) } @@ -513,73 +519,7 @@ func (e *Environment) ComputeSourcesURI() []string { interceptors = append(interceptors, e.Interceptors...) } if len(interceptors) > 0 { - params = append(params, "interceptors="+strings.Join(interceptors, ",")) - } - - if len(params) > 0 { - src = fmt.Sprintf("%s?%s", src, strings.Join(params, "&")) - } - - paths = append(paths, src) - } - - return paths -} - -// AddSourcesProperties -- -func (e *Environment) AddSourcesProperties() { - sources := e.Integration.Sources() - properties := make(map[string]string) - - for _, s := range sources { - if s.Type == v1.SourceTypeKamelet { - // We compute properties only for Kamelets - // TODO move other sources types to this format instead of ENV_VAR - - srcName := strings.TrimPrefix(s.Name, "/") - kameletName := srcName - if strings.Contains(kameletName, ".") { - kameletName = kameletName[0:strings.LastIndex(kameletName, ".")] - } - root := path.Join(KameletsMountPath, kameletName) - - src := path.Join(root, srcName) - src = "file:" + src - properties[fmt.Sprintf("camel.k.kamelets[%s].location", kameletName)] = src - - schemaName := path.Join(root, fmt.Sprintf("%s-schema.json", kameletName)) - properties[fmt.Sprintf("camel.k.kamelets[%s].schema", kameletName)] = schemaName - - if s.InferLanguage() != "" { - properties[fmt.Sprintf("camel.k.kamelets[%s].language", kameletName)] = string(s.InferLanguage()) - } - if s.Loader != "" { - properties[fmt.Sprintf("camel.k.kamelets[%s].loader", kameletName)] = s.Loader - } - if s.Compression { - properties[fmt.Sprintf("camel.k.kamelets[%s].compression", kameletName)] = True - } - - interceptors := make([]string, 0, len(s.Interceptors)) - if s.Interceptors != nil { - interceptors = append(interceptors, s.Interceptors...) - } - if e.Interceptors != nil { - interceptors = append(interceptors, e.Interceptors...) - } - for i, interceptor := range interceptors { - properties[fmt.Sprintf("camel.k.kamelets[%s].interceptors[%d]", kameletName, i)] = interceptor - } - } - } - - if len(properties) > 0 { - if e.ApplicationProperties == nil { - e.ApplicationProperties = properties - } else { - for k, v := range properties { - e.ApplicationProperties[k] = v - } + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors", i)] = strings.Join(interceptors, ",") } } } @@ -596,67 +536,30 @@ func (e *Environment) ConfigureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c cmName = s.ContentRef } resName := strings.TrimPrefix(s.Name, "/") + refName := fmt.Sprintf("i-source-%03d", i) + resPath := path.Join(SourcesMountPath, refName) - if s.Type == v1.SourceTypeKamelet { - kameletName := resName - if strings.Contains(kameletName, ".") { - kameletName = kameletName[0:strings.LastIndex(kameletName, ".")] - } - refName := fmt.Sprintf("i-kamelet-source-%03d", i) - resPath := path.Join(KameletsMountPath, kameletName) - schemaResName := fmt.Sprintf("%s-schema.json", kameletName) - - *vols = append(*vols, corev1.Volume{ - Name: refName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: cmName, - }, - Items: []corev1.KeyToPath{ - { - Key: "content", - Path: resName, - }, - { - Key: "schema", - Path: schemaResName, - }, - }, + *vols = append(*vols, corev1.Volume{ + Name: refName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: cmName, }, - }, - }) - - *mnts = append(*mnts, corev1.VolumeMount{ - Name: refName, - MountPath: resPath, - }) - } else { - refName := fmt.Sprintf("i-source-%03d", i) - resPath := path.Join(SourcesMountPath, refName) - - *vols = append(*vols, corev1.Volume{ - Name: refName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: cmName, - }, - Items: []corev1.KeyToPath{ - { - Key: "content", - Path: resName, - }, + Items: []corev1.KeyToPath{ + { + Key: "content", + Path: resName, }, }, }, - }) + }, + }) - *mnts = append(*mnts, corev1.VolumeMount{ - Name: refName, - MountPath: resPath, - }) - } + *mnts = append(*mnts, corev1.VolumeMount{ + Name: refName, + MountPath: resPath, + }) } for i, r := range e.Integration.Resources() {
