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 8ba04e79a203d8fe382731ab3d1e5d2db9ef45da Author: nicolaferraro <ni.ferr...@gmail.com> AuthorDate: Wed Dec 15 10:36:40 2021 +0100 Fix #1107: initial trait --- addons/keda/duck/v1alpha1/doc.go | 21 ++ addons/keda/duck/v1alpha1/duck_types.go | 108 ++++++++++ .../v1alpha1/duck_types_support.go} | 42 ++-- addons/keda/duck/v1alpha1/register.go | 57 +++++ addons/keda/duck/v1alpha1/zz_generated.deepcopy.go | 235 +++++++++++++++++++++ addons/keda/keda.go | 118 ++++++++++- docs/modules/ROOT/nav.adoc | 1 + docs/modules/traits/pages/keda.adoc | 44 ++++ go.sum | 1 + pkg/cmd/run.go | 7 +- pkg/resources/resources.go | 4 +- resources/traits.yaml | 23 ++ script/Makefile | 8 +- script/{gen_doc.sh => gen_client_keda.sh} | 16 +- script/gen_doc.sh | 2 +- 15 files changed, 645 insertions(+), 42 deletions(-) diff --git a/addons/keda/duck/v1alpha1/doc.go b/addons/keda/duck/v1alpha1/doc.go new file mode 100644 index 0000000..56d897a --- /dev/null +++ b/addons/keda/duck/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +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 duck contains a partial schema of the Keda APIs +// +kubebuilder:object:generate=true +// +groupName=keda.sh +package v1alpha1 diff --git a/addons/keda/duck/v1alpha1/duck_types.go b/addons/keda/duck/v1alpha1/duck_types.go new file mode 100644 index 0000000..8504b6c --- /dev/null +++ b/addons/keda/duck/v1alpha1/duck_types.go @@ -0,0 +1,108 @@ +/* +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 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:onlyVerbs=get,list,watch +// +genclient:noStatus +// +kubebuilder:object:root=true + +// ScaledObject is a specification for a ScaledObject resource +type ScaledObject struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ScaledObjectSpec `json:"spec"` +} + +// ScaledObjectSpec is the spec for a ScaledObject resource +type ScaledObjectSpec struct { + ScaleTargetRef *v1.ObjectReference `json:"scaleTargetRef"` + + Triggers []ScaleTriggers `json:"triggers"` +} + +// ScaleTriggers reference the scaler that will be used +type ScaleTriggers struct { + Type string `json:"type"` + // +optional + Name string `json:"name,omitempty"` + Metadata map[string]string `json:"metadata"` + // +optional + AuthenticationRef *ScaledObjectAuthRef `json:"authenticationRef,omitempty"` + // +optional + FallbackReplicas *int32 `json:"fallback,omitempty"` +} + +// ScaledObjectAuthRef points to the TriggerAuthentication or ClusterTriggerAuthentication object that +// is used to authenticate the scaler with the environment +type ScaledObjectAuthRef struct { + Name string `json:"name"` + // Kind of the resource being referred to. Defaults to TriggerAuthentication. + // +optional + Kind string `json:"kind,omitempty"` +} + +// +kubebuilder:object:root=true + +// ScaledObjectList contains a list of ScaledObject. +type ScaledObjectList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ScaledObject `json:"items"` +} + +// +genclient +// +genclient:onlyVerbs=get,list,watch +// +genclient:noStatus +// +kubebuilder:object:root=true + +// TriggerAuthentication defines how a trigger can authenticate +type TriggerAuthentication struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TriggerAuthenticationSpec `json:"spec"` +} + +// TriggerAuthenticationSpec defines the various ways to authenticate +type TriggerAuthenticationSpec struct { + // +optional + SecretTargetRef []AuthSecretTargetRef `json:"secretTargetRef,omitempty"` +} + +// AuthSecretTargetRef is used to authenticate using a reference to a secret +type AuthSecretTargetRef struct { + Parameter string `json:"parameter"` + Name string `json:"name"` + Key string `json:"key"` +} + +// +kubebuilder:object:root=true + +// TriggerAuthenticationList contains a list of TriggerAuthentication +type TriggerAuthenticationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []TriggerAuthentication `json:"items"` +} diff --git a/addons/keda/keda.go b/addons/keda/duck/v1alpha1/duck_types_support.go similarity index 50% copy from addons/keda/keda.go copy to addons/keda/duck/v1alpha1/duck_types_support.go index c794249..c8c2f23 100644 --- a/addons/keda/keda.go +++ b/addons/keda/duck/v1alpha1/duck_types_support.go @@ -15,37 +15,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -package keda +package v1alpha1 import ( - "github.com/apache/camel-k/pkg/trait" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// The Keda trait can be used for automatic integration with Keda autoscalers. -// -// The Keda trait is disabled by default. -// -// +camel-k:trait=keda. -type kedaTrait struct { - trait.BaseTrait `property:",squash"` - // Enables automatic configuration of the trait. - Auto *bool `property:"auto" json:"auto,omitempty"` - // Metadata - Metadata map[string]string `property:"metadata" json:"metadata,omitempty"` -} +const ( + ScaledObjectKind = "ScaledObject" +) -// NewKedaTrait --. -func NewKedaTrait() trait.Trait { - return &kedaTrait{ - BaseTrait: trait.NewBaseTrait("keda", trait.TraitOrderPostProcessResources), +func NewScaledObject(namespace string, name string) ScaledObject { + return ScaledObject{ + TypeMeta: metav1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: ScaledObjectKind, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, } } - -func (t *kedaTrait) Configure(e *trait.Environment) (bool, error) { - - return false, nil -} - -func (t *kedaTrait) Apply(e *trait.Environment) error { - return nil -} diff --git a/addons/keda/duck/v1alpha1/register.go b/addons/keda/duck/v1alpha1/register.go new file mode 100644 index 0000000..a3814da --- /dev/null +++ b/addons/keda/duck/v1alpha1/register.go @@ -0,0 +1,57 @@ +/* +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 ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const ( + KedaGroup = "keda.sh" + KedaVersion = "v1alpha1" +) + +var ( + // SchemeGroupVersion is group version used to register these objects. + SchemeGroupVersion = schema.GroupVersion{Group: KedaGroup, Version: KedaVersion} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + + // AddToScheme is a shortcut to SchemeBuilder.AddToScheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ScaledObject{}, + &ScaledObjectList{}, + &TriggerAuthentication{}, + &TriggerAuthenticationList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/addons/keda/duck/v1alpha1/zz_generated.deepcopy.go b/addons/keda/duck/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000..b551c7f --- /dev/null +++ b/addons/keda/duck/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,235 @@ +// +build !ignore_autogenerated + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthSecretTargetRef) DeepCopyInto(out *AuthSecretTargetRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSecretTargetRef. +func (in *AuthSecretTargetRef) DeepCopy() *AuthSecretTargetRef { + if in == nil { + return nil + } + out := new(AuthSecretTargetRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaleTriggers) DeepCopyInto(out *ScaleTriggers) { + *out = *in + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.AuthenticationRef != nil { + in, out := &in.AuthenticationRef, &out.AuthenticationRef + *out = new(ScaledObjectAuthRef) + **out = **in + } + if in.FallbackReplicas != nil { + in, out := &in.FallbackReplicas, &out.FallbackReplicas + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaleTriggers. +func (in *ScaleTriggers) DeepCopy() *ScaleTriggers { + if in == nil { + return nil + } + out := new(ScaleTriggers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaledObject) DeepCopyInto(out *ScaledObject) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaledObject. +func (in *ScaledObject) DeepCopy() *ScaledObject { + if in == nil { + return nil + } + out := new(ScaledObject) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScaledObject) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaledObjectAuthRef) DeepCopyInto(out *ScaledObjectAuthRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaledObjectAuthRef. +func (in *ScaledObjectAuthRef) DeepCopy() *ScaledObjectAuthRef { + if in == nil { + return nil + } + out := new(ScaledObjectAuthRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaledObjectList) DeepCopyInto(out *ScaledObjectList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ScaledObject, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaledObjectList. +func (in *ScaledObjectList) DeepCopy() *ScaledObjectList { + if in == nil { + return nil + } + out := new(ScaledObjectList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScaledObjectList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaledObjectSpec) DeepCopyInto(out *ScaledObjectSpec) { + *out = *in + if in.ScaleTargetRef != nil { + in, out := &in.ScaleTargetRef, &out.ScaleTargetRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.Triggers != nil { + in, out := &in.Triggers, &out.Triggers + *out = make([]ScaleTriggers, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaledObjectSpec. +func (in *ScaledObjectSpec) DeepCopy() *ScaledObjectSpec { + if in == nil { + return nil + } + out := new(ScaledObjectSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerAuthentication) DeepCopyInto(out *TriggerAuthentication) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerAuthentication. +func (in *TriggerAuthentication) DeepCopy() *TriggerAuthentication { + if in == nil { + return nil + } + out := new(TriggerAuthentication) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TriggerAuthentication) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerAuthenticationList) DeepCopyInto(out *TriggerAuthenticationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TriggerAuthentication, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerAuthenticationList. +func (in *TriggerAuthenticationList) DeepCopy() *TriggerAuthenticationList { + if in == nil { + return nil + } + out := new(TriggerAuthenticationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TriggerAuthenticationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TriggerAuthenticationSpec) DeepCopyInto(out *TriggerAuthenticationSpec) { + *out = *in + if in.SecretTargetRef != nil { + in, out := &in.SecretTargetRef, &out.SecretTargetRef + *out = make([]AuthSecretTargetRef, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TriggerAuthenticationSpec. +func (in *TriggerAuthenticationSpec) DeepCopy() *TriggerAuthenticationSpec { + if in == nil { + return nil + } + out := new(TriggerAuthenticationSpec) + in.DeepCopyInto(out) + return out +} diff --git a/addons/keda/keda.go b/addons/keda/keda.go index c794249..65a8bd4 100644 --- a/addons/keda/keda.go +++ b/addons/keda/keda.go @@ -18,7 +18,16 @@ limitations under the License. package keda import ( + "strings" + + kedav1alpha1 "github.com/apache/camel-k/addons/keda/duck/v1alpha1" + camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + camelv1alpha1 "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/trait" + scase "github.com/stoewer/go-strcase" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" ) // The Keda trait can be used for automatic integration with Keda autoscalers. @@ -30,7 +39,16 @@ type kedaTrait struct { trait.BaseTrait `property:",squash"` // Enables automatic configuration of the trait. Auto *bool `property:"auto" json:"auto,omitempty"` - // Metadata + // Convert metadata properties to camelCase (needed because trait properties use kebab-case). Enabled by default. + CamelCaseConversion *bool `property:"camel-case-conversion" json:"camelCaseConversion,omitempty"` + // Set the spec->replicas field on the top level controller to an explicit value if missing, to allow Keda to recognize it as a scalable resource + HackControllerReplicas *bool `property:"hack-controller-replicas" json:"hackControllerReplicas,omitempty"` + // Triggers + Triggers []kedaTrigger `property:"triggers" json:"triggers,omitempty"` +} + +type kedaTrigger struct { + Type string `property:"type" json:"type,omitempty"` Metadata map[string]string `property:"metadata" json:"metadata,omitempty"` } @@ -42,10 +60,106 @@ func NewKedaTrait() trait.Trait { } func (t *kedaTrait) Configure(e *trait.Environment) (bool, error) { + if t.Enabled == nil || !*t.Enabled { + return false, nil + } + + if !e.IntegrationInPhase(camelv1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() { + return false, nil + } - return false, nil + return true, nil } func (t *kedaTrait) Apply(e *trait.Environment) error { + if e.IntegrationInPhase(camelv1.IntegrationPhaseInitialization) { + if t.HackControllerReplicas == nil || *t.HackControllerReplicas { + if err := t.hackControllerReplicas(e); err != nil { + return err + } + } + } else if e.IntegrationInRunningPhases() { + if so, err := t.getScaledObject(e); err != nil { + return err + } else if so != nil { + e.Resources.Add(so) + } + } + return nil } + +func (t *kedaTrait) getScaledObject(e *trait.Environment) (*kedav1alpha1.ScaledObject, error) { + if len(t.Triggers) == 0 { + return nil, nil + } + obj := kedav1alpha1.NewScaledObject(e.Integration.Namespace, e.Integration.Name) + obj.Spec.ScaleTargetRef = t.getTopControllerReference(e) + + for _, trigger := range t.Triggers { + meta := make(map[string]string) + for k, v := range trigger.Metadata { + kk := k + if t.CamelCaseConversion == nil || *t.CamelCaseConversion { + kk = scase.LowerCamelCase(k) + } + meta[kk] = v + } + st := kedav1alpha1.ScaleTriggers{ + Type: trigger.Type, + Metadata: meta, + } + obj.Spec.Triggers = append(obj.Spec.Triggers, st) + } + + return &obj, nil +} + +func (t *kedaTrait) hackControllerReplicas(e *trait.Environment) error { + ctrlRef := t.getTopControllerReference(e) + + if ctrlRef.Kind == camelv1alpha1.KameletBindingKind { + // Update the KameletBinding directly (do not add it to env resources, it's the integration parent) + key := client.ObjectKey{ + Namespace: e.Integration.Namespace, + Name: ctrlRef.Name, + } + klb := camelv1alpha1.KameletBinding{} + if err := e.Client.Get(e.Ctx, key, &klb); err != nil { + return err + } + if klb.Spec.Replicas == nil { + one := int32(1) + klb.Spec.Replicas = &one + if err := e.Client.Update(e.Ctx, &klb); err != nil { + return err + } + } + } else { + if e.Integration.Spec.Replicas == nil { + one := int32(1) + e.Integration.Spec.Replicas = &one + if err := e.Client.Update(e.Ctx, e.Integration); err != nil { + return err + } + } + } + return nil +} + +func (t *kedaTrait) getTopControllerReference(e *trait.Environment) *v1.ObjectReference { + for _, o := range e.Integration.OwnerReferences { + if o.Kind == v1alpha1.KameletBindingKind && strings.HasPrefix(o.APIVersion, v1alpha1.SchemeGroupVersion.Group) { + return &v1.ObjectReference{ + APIVersion: o.APIVersion, + Kind: o.Kind, + Name: o.Name, + } + } + } + return &v1.ObjectReference{ + APIVersion: e.Integration.APIVersion, + Kind: e.Integration.Kind, + Name: e.Integration.Name, + } +} diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 593ab84..890e733 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -63,6 +63,7 @@ ** xref:traits:jolokia.adoc[Jolokia] ** xref:traits:jvm.adoc[Jvm] ** xref:traits:kamelets.adoc[Kamelets] +** xref:traits:keda.adoc[Keda] ** xref:traits:knative-service.adoc[Knative Service] ** xref:traits:knative.adoc[Knative] ** xref:traits:logging.adoc[Logging] diff --git a/docs/modules/traits/pages/keda.adoc b/docs/modules/traits/pages/keda.adoc new file mode 100644 index 0000000..a73dabd --- /dev/null +++ b/docs/modules/traits/pages/keda.adoc @@ -0,0 +1,44 @@ += Keda Trait + +// Start of autogenerated code - DO NOT EDIT! (description) +The Keda trait can be used for automatic integration with Keda autoscalers. + +The Keda trait is disabled by default. + + +This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. + +// End of autogenerated code - DO NOT EDIT! (description) +// Start of autogenerated code - DO NOT EDIT! (configuration) +== Configuration + +Trait properties can be specified when running any integration with the CLI: +[source,console] +---- +$ kamel run --trait keda.[key]=[value] --trait keda.[key2]=[value2] integration.groovy +---- +The following configuration options are available: + +[cols="2m,1m,5a"] +|=== +|Property | Type | Description + +| keda.enabled +| bool +| Can be used to enable or disable a trait. All traits share this common property. + +| keda.auto +| bool +| Enables automatic configuration of the trait. + +| keda.camel-case-conversion +| bool +| Convert metadata properties to camelCase (needed because trait properties use kebab-case). Enabled by default. + +| keda.triggers +| []github.com/apache/camel-k/addons/keda.kedaTrigger +| Triggers + +|=== + +// End of autogenerated code - DO NOT EDIT! (configuration) diff --git a/go.sum b/go.sum index a7e63c9..9aaf745 100644 --- a/go.sum +++ b/go.sum @@ -1803,6 +1803,7 @@ k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRV k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/code-generator v0.21.4 h1:vO8jVuEGV4UF+/2s/88Qg05MokE/1QUFi/Q2YDgz++A= k8s.io/code-generator v0.21.4/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 5dfca09..1819405 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -292,8 +292,11 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error { tp := catalog.ComputeTraitsProperties() for _, t := range o.Traits { kv := strings.SplitN(t, "=", 2) - - if !util.StringSliceExists(tp, kv[0]) { + prefix := kv[0] + if strings.Contains(prefix, "[") { + prefix = prefix[0:strings.Index(prefix, "[")] + } + if !util.StringSliceExists(tp, prefix) { fmt.Printf("Error: %s is not a valid trait property\n", t) return nil } diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go index b798a6a..a979664 100644 --- a/pkg/resources/resources.go +++ b/pkg/resources/resources.go @@ -541,9 +541,9 @@ var assets = func() http.FileSystem { "/traits.yaml": &vfsgen۰CompressedFileInfo{ name: "traits.yaml", modTime: time.Time{}, - uncompressedSize: 46896, + uncompressedSize: 47743, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x1c\xb7\xb1\xe0\xef\xfe\x2b\x50\x7c\x57\x25\x92\xb5\xbb\x94\x9d\x97\x3c\x1f\xef\x74\x29\x5a\x92\x13\xda\xfa\xe0\x49\xb2\x73\x29\x9f\x2b\x8b\x9d\xe9\xdd\x85\x38\x0b\x4c\x00\x0c\xa9\xcd\xbd\xfb\xdf\xaf\xd0\xdd\xf8\x98\xd9\x5d\x72\x29\x91\x7e\xe1\xd5\x4b\x7e\xb0\x48\x0e\x80\x46\xa3\xd1\xdf\xdd\xf0\x56\x2a\xef\x4e\xbf\x1a\x0b\x2d\x57\x70\x2a\xe4\x7c\xae\xb4\xf2\xeb\xaf\x84\x68\x1b\xe9\xe7\xc6\xae\x4e\xc5\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x1c\xb7\xb1\xe0\xef\xfe\x2b\x50\x7c\x57\x25\x92\xb5\xbb\x94\x9d\x97\xc4\xc7\x3b\x5d\x8a\x96\xe4\x98\xb6\x3e\x78\x92\xec\x5c\x4a\xe7\xca\x62\x67\x7a\x77\x21\x62\x80\x09\x80\x21\xb5\xb9\x77\xff\xfb\x2b\x74\xe3\x6b\x66\x77\xc9\xa1\x24\xfa\x85\x55\x79\xa9\x7a\x16\xc9\x01\xd0\xdd\x68\x34\xfa\x1b\xce\x70\xe1\xec\xe9\x57\x53\xa6\x78\x03\xa7\x8c\x2f\x97\x42\x09\xb7\xf9\x8a\xb1\x56\x72\xb7\xd4\xa6\x39\x65\x4b\x [...] }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/resources/traits.yaml b/resources/traits.yaml index 2b66ec4..7bd54bf 100755 --- a/resources/traits.yaml +++ b/resources/traits.yaml @@ -570,6 +570,29 @@ traits: - name: list type: string description: Comma separated list of Kamelet names to load into the current integration +- name: keda + platform: false + profiles: + - Kubernetes + - Knative + - OpenShift + description: The Keda trait can be used for automatic integration with Keda autoscalers. + The Keda trait is disabled by default. + 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: Enables automatic configuration of the trait. + - name: camel-case-conversion + type: bool + description: Convert metadata properties to camelCase (needed because trait properties + use kebab-case). Enabled by default. + - name: triggers + type: '[]github.com/apache/camel-k/addons/keda.kedaTrigger' + description: Triggers - name: knative-service platform: false profiles: diff --git a/script/Makefile b/script/Makefile index be57f3b..af03077 100644 --- a/script/Makefile +++ b/script/Makefile @@ -155,7 +155,7 @@ codegen: gofmt -w pkg/util/defaults/defaults.go -generate: generate-deepcopy generate-crd generate-client generate-doc generate-json-schema generate-strimzi +generate: generate-deepcopy generate-crd generate-client generate-doc generate-json-schema generate-keda generate-strimzi generate-client: ./script/gen_client.sh @@ -173,6 +173,10 @@ generate-json-schema: # Skip since the YAML DSL schema has been moved to apache/camel #./script/gen_json_schema.sh $(RUNTIME_VERSION) $(STAGING_RUNTIME_REPO) +generate-keda: + cd addons/keda/duck && $(CONTROLLER_GEN) paths="./..." object + ./script/gen_client_keda.sh + generate-strimzi: cd addons/strimzi/duck && $(CONTROLLER_GEN) paths="./..." object ./script/gen_client_strimzi.sh @@ -359,7 +363,7 @@ install-minikube: get-staging-repo: @echo $(or ${STAGING_RUNTIME_REPO},https://repository.apache.org/content/repositories/snapshots@id=apache-snapshots@snapshots) -.PHONY: build build-kamel build-resources dep codegen images images-dev images-push images-push-staging test check test-integration clean release cross-compile package-examples set-version git-tag release-notes check-licenses generate-deepcopy generate-client generate-doc build-resources release-helm release-staging release-nightly get-staging-repo get-version build-submodules set-module-version bundle-kamelets generate-strimzi +.PHONY: build build-kamel build-resources dep codegen images images-dev images-push images-push-staging test check test-integration clean release cross-compile package-examples set-version git-tag release-notes check-licenses generate-deepcopy generate-client generate-doc build-resources release-helm release-staging release-nightly get-staging-repo get-version build-submodules set-module-version bundle-kamelets generate-keda generate-strimzi # find or download controller-gen if necessary controller-gen: diff --git a/script/gen_doc.sh b/script/gen_client_keda.sh similarity index 70% copy from script/gen_doc.sh copy to script/gen_client_keda.sh index d4d6aab..e5dd2ca 100755 --- a/script/gen_doc.sh +++ b/script/gen_client_keda.sh @@ -15,14 +15,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +set -e + location=$(dirname $0) rootdir=$location/.. -echo "Generating API documentation..." -$location/gen_crd/gen_crd_api.sh -echo "Generating API documentation... done!" +unset GOPATH +GO111MODULE=on + +echo "Generating boilerplate code for Keda addon..." -echo "Generating traits documentation..." cd $rootdir -go run ./cmd/util/doc-gen --input-dirs ./pkg/trait --input-dirs ./addons/master --input-dirs ./addons/threescale --input-dirs ./addons/tracing -echo "Generating traits documentation... done!" + +go run k8s.io/code-generator/cmd/deepcopy-gen \ + -h ./script/headers/default.txt \ + --input-dirs=github.com/apache/camel-k/addons/keda diff --git a/script/gen_doc.sh b/script/gen_doc.sh index d4d6aab..028ec44 100755 --- a/script/gen_doc.sh +++ b/script/gen_doc.sh @@ -24,5 +24,5 @@ echo "Generating API documentation... done!" echo "Generating traits documentation..." cd $rootdir -go run ./cmd/util/doc-gen --input-dirs ./pkg/trait --input-dirs ./addons/master --input-dirs ./addons/threescale --input-dirs ./addons/tracing +go run ./cmd/util/doc-gen --input-dirs github.com/apache/camel-k/pkg/trait --input-dirs github.com/apache/camel-k/addons/keda --input-dirs github.com/apache/camel-k/addons/master --input-dirs github.com/apache/camel-k/addons/threescale --input-dirs github.com/apache/camel-k/addons/tracing echo "Generating traits documentation... done!"