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 2022/01/12 08:15:18 UTC
[camel-k] 18/22: Fix #1107: fix findings
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 9d89922951da6dcfc258d7fad097e7e47b78a4dc
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Wed Dec 22 00:54:16 2021 +0100
Fix #1107: fix findings
---
addons/keda/keda.go | 43 ++++++-------
addons/keda/keda_test.go | 61 ++++++++++++++++---
docs/modules/traits/pages/keda.adoc | 4 --
e2e/common/scale_binding_test.go | 11 +---
e2e/common/scale_integration_test.go | 11 +---
pkg/client/{serverside.go => apply.go} | 0
pkg/client/client.go | 2 +
pkg/client/scale.go | 35 +++++++++++
pkg/cmd/run.go | 2 +-
pkg/resources/resources.go | 4 +-
pkg/trait/deployer.go | 108 +--------------------------------
pkg/util/test/client.go | 45 +++++++++++++-
resources/traits.yaml | 4 --
13 files changed, 157 insertions(+), 173 deletions(-)
diff --git a/addons/keda/keda.go b/addons/keda/keda.go
index ad9f71d..e6e1d5e 100644
--- a/addons/keda/keda.go
+++ b/addons/keda/keda.go
@@ -38,7 +38,7 @@ import (
"github.com/apache/camel-k/pkg/util/source"
"github.com/apache/camel-k/pkg/util/uri"
"github.com/pkg/errors"
- scase "github.com/stoewer/go-strcase"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
@@ -76,8 +76,6 @@ type kedaTrait struct {
trait.BaseTrait `property:",squash"`
// Enables automatic configuration of the trait. Allows the trait to infer KEDA triggers from the Kamelets.
Auto *bool `property:"auto" json:"auto,omitempty"`
- // Convert metadata properties to camelCase (needed because Camel K trait properties use kebab-case from command line). Disabled 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"`
// Interval (seconds) to check each trigger on.
@@ -170,11 +168,7 @@ func (t *kedaTrait) addScalingResources(e *trait.Environment) error {
for idx, 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
+ meta[k] = v
}
var authenticationRef *kedav1alpha1.ScaledObjectAuthRef
if len(trigger.authentication) > 0 && trigger.AuthenticationSecret != "" {
@@ -269,28 +263,25 @@ func (t *kedaTrait) addScalingResources(e *trait.Environment) error {
func (t *kedaTrait) hackControllerReplicas(e *trait.Environment) error {
ctrlRef := t.getTopControllerReference(e)
+ scale := autoscalingv1.Scale{
+ Spec: autoscalingv1.ScaleSpec{
+ Replicas: int32(1),
+ },
+ }
+ scalesClient, err := e.Client.ScalesClient()
+ if err != nil {
+ return err
+ }
if ctrlRef.Kind == camelv1alpha1.KameletBindingKind {
- // Update the KameletBinding directly (do not add it to env resources, it's the integration parent)
- key := ctrl.ObjectKey{
- Namespace: e.Integration.Namespace,
- Name: ctrlRef.Name,
- }
- klb := camelv1alpha1.KameletBinding{}
- if err := e.Client.Get(e.Ctx, key, &klb); err != nil {
+ scale.ObjectMeta.Name = ctrlRef.Name
+ _, err = scalesClient.Scales(e.Integration.Namespace).Update(e.Ctx, camelv1alpha1.SchemeGroupVersion.WithResource("kameletbindings").GroupResource(), &scale, metav1.UpdateOptions{})
+ if 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
- // Update the Integration directly as the spec section is not merged by default
- if err := e.Client.Update(e.Ctx, e.Integration); err != nil {
+ scale.ObjectMeta.Name = e.Integration.Name
+ _, err = scalesClient.Scales(e.Integration.Namespace).Update(e.Ctx, camelv1.SchemeGroupVersion.WithResource("integrations").GroupResource(), &scale, metav1.UpdateOptions{})
+ if err != nil {
return err
}
}
diff --git a/addons/keda/keda_test.go b/addons/keda/keda_test.go
index 08a627e..4783653 100644
--- a/addons/keda/keda_test.go
+++ b/addons/keda/keda_test.go
@@ -35,7 +35,6 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
- "sigs.k8s.io/controller-runtime/pkg/client"
)
var (
@@ -348,14 +347,58 @@ func TestHackReplicas(t *testing.T) {
assert.NoError(t, err)
assert.True(t, res)
assert.NoError(t, keda.Apply(env))
- it := camelv1.Integration{}
- key := client.ObjectKey{
- Namespace: "test",
- Name: "my-it",
- }
- assert.NoError(t, env.Client.Get(env.Ctx, key, &it))
- assert.NotNil(t, it.Spec.Replicas)
- assert.Equal(t, int32(1), *it.Spec.Replicas)
+ scalesClient, err := env.Client.ScalesClient()
+ assert.NoError(t, err)
+ sc, err := scalesClient.Scales("test").Get(env.Ctx, camelv1.SchemeGroupVersion.WithResource("integrations").GroupResource(), "my-it", metav1.GetOptions{})
+ assert.NoError(t, err)
+ assert.Equal(t, int32(1), sc.Spec.Replicas)
+}
+
+func TestHackKLBReplicas(t *testing.T) {
+ keda, _ := NewKedaTrait().(*kedaTrait)
+ keda.Enabled = &testingTrue
+ keda.Auto = &testingFalse
+ keda.Triggers = append(keda.Triggers, kedaTrigger{
+ Type: "custom",
+ Metadata: map[string]string{
+ "a": "b",
+ },
+ })
+ keda.HackControllerReplicas = &testingTrue
+ env := createBasicTestEnvironment(
+ &camelv1alpha1.KameletBinding{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "my-klb",
+ },
+ },
+ &camelv1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "my-it",
+ OwnerReferences: []metav1.OwnerReference{
+ {
+ APIVersion: camelv1alpha1.SchemeGroupVersion.String(),
+ Kind: "KameletBinding",
+ Name: "my-klb",
+ },
+ },
+ },
+ Status: camelv1.IntegrationStatus{
+ Phase: camelv1.IntegrationPhaseInitialization,
+ },
+ },
+ )
+
+ res, err := keda.Configure(env)
+ assert.NoError(t, err)
+ assert.True(t, res)
+ assert.NoError(t, keda.Apply(env))
+ scalesClient, err := env.Client.ScalesClient()
+ assert.NoError(t, err)
+ sc, err := scalesClient.Scales("test").Get(env.Ctx, camelv1alpha1.SchemeGroupVersion.WithResource("kameletbindings").GroupResource(), "my-klb", metav1.GetOptions{})
+ assert.NoError(t, err)
+ assert.Equal(t, int32(1), sc.Spec.Replicas)
}
func getScaledObject(e *trait.Environment) *v1alpha1.ScaledObject {
diff --git a/docs/modules/traits/pages/keda.adoc b/docs/modules/traits/pages/keda.adoc
index df6c8d9..b1a5827 100644
--- a/docs/modules/traits/pages/keda.adoc
+++ b/docs/modules/traits/pages/keda.adoc
@@ -38,10 +38,6 @@ The following configuration options are available:
| bool
| Enables automatic configuration of the trait. Allows the trait to infer KEDA triggers from the Kamelets.
-| keda.camel-case-conversion
-| bool
-| Convert metadata properties to camelCase (needed because Camel K trait properties use kebab-case from command line). Disabled by default.
-
| keda.hack-controller-replicas
| bool
| 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.
diff --git a/e2e/common/scale_binding_test.go b/e2e/common/scale_binding_test.go
index 49d9668..3bbc2ee 100644
--- a/e2e/common/scale_binding_test.go
+++ b/e2e/common/scale_binding_test.go
@@ -33,10 +33,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
- "k8s.io/client-go/dynamic"
- "k8s.io/client-go/restmapper"
- "k8s.io/client-go/scale"
-
. "github.com/apache/camel-k/e2e/support"
v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -80,12 +76,7 @@ func TestKameletBindingScale(t *testing.T) {
t.Run("Scale kamelet binding with polymorphic client", func(t *testing.T) {
RegisterTestingT(t)
- // Polymorphic scale client
- groupResources, err := restmapper.GetAPIGroupResources(TestClient().Discovery())
- Expect(err).To(BeNil())
- mapper := restmapper.NewDiscoveryRESTMapper(groupResources)
- resolver := scale.NewDiscoveryScaleKindResolver(TestClient().Discovery())
- scaleClient, err := scale.NewForConfig(TestClient().GetConfig(), mapper, dynamic.LegacyAPIPathResolverFunc, resolver)
+ scaleClient, err := TestClient().ScalesClient()
Expect(err).To(BeNil())
// Patch the integration scale subresource
diff --git a/e2e/common/scale_integration_test.go b/e2e/common/scale_integration_test.go
index 5c70901..1c01d1c 100644
--- a/e2e/common/scale_integration_test.go
+++ b/e2e/common/scale_integration_test.go
@@ -33,10 +33,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
- "k8s.io/client-go/dynamic"
- "k8s.io/client-go/restmapper"
- "k8s.io/client-go/scale"
-
. "github.com/apache/camel-k/e2e/support"
v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/client/camel/clientset/versioned"
@@ -67,12 +63,7 @@ func TestIntegrationScale(t *testing.T) {
t.Run("Scale integration with polymorphic client", func(t *testing.T) {
RegisterTestingT(t)
- // Polymorphic scale client
- groupResources, err := restmapper.GetAPIGroupResources(TestClient().Discovery())
- Expect(err).To(BeNil())
- mapper := restmapper.NewDiscoveryRESTMapper(groupResources)
- resolver := scale.NewDiscoveryScaleKindResolver(TestClient().Discovery())
- scaleClient, err := scale.NewForConfig(TestClient().GetConfig(), mapper, dynamic.LegacyAPIPathResolverFunc, resolver)
+ scaleClient, err := TestClient().ScalesClient()
Expect(err).To(BeNil())
// Patch the integration scale subresource
diff --git a/pkg/client/serverside.go b/pkg/client/apply.go
similarity index 100%
rename from pkg/client/serverside.go
rename to pkg/client/apply.go
diff --git a/pkg/client/client.go b/pkg/client/client.go
index 2cf73c2..967a5fc 100644
--- a/pkg/client/client.go
+++ b/pkg/client/client.go
@@ -26,6 +26,7 @@ import (
user "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "k8s.io/client-go/scale"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
@@ -64,6 +65,7 @@ type Client interface {
GetConfig() *rest.Config
GetCurrentNamespace(kubeConfig string) (string, error)
ServerOrClientSideApplier() ServerOrClientSideApplier
+ ScalesClient() (scale.ScalesGetter, error)
}
// Injectable identifies objects that can receive a Client.
diff --git a/pkg/client/scale.go b/pkg/client/scale.go
new file mode 100644
index 0000000..7bcf7d7
--- /dev/null
+++ b/pkg/client/scale.go
@@ -0,0 +1,35 @@
+/*
+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 client
+
+import (
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/restmapper"
+ "k8s.io/client-go/scale"
+)
+
+func (c *defaultClient) ScalesClient() (scale.ScalesGetter, error) {
+ // Polymorphic scale client
+ groupResources, err := restmapper.GetAPIGroupResources(c.Discovery())
+ if err != nil {
+ return nil, err
+ }
+ mapper := restmapper.NewDiscoveryRESTMapper(groupResources)
+ resolver := scale.NewDiscoveryScaleKindResolver(c.Discovery())
+ return scale.NewForConfig(c.GetConfig(), mapper, dynamic.LegacyAPIPathResolverFunc, resolver)
+}
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index d2d260f..4721fef 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -54,7 +54,7 @@ import (
"github.com/apache/camel-k/pkg/util/watch"
)
-var traitConfigRegexp = regexp.MustCompile(`^([a-z0-9-]+)((?:\[[0-9]+\]|\.[a-z0-9-]+)+)=(.*)$`)
+var traitConfigRegexp = regexp.MustCompile(`^([a-z0-9-]+)((?:\.[a-z0-9-]+)(?:\[[0-9]+\]|\.[A-Za-z0-9-_]+)*)=(.*)$`)
func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) {
options := runCmdOptions{
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index 80a8c6d..5d8301d 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -555,9 +555,9 @@ var assets = func() http.FileSystem {
"/traits.yaml": &vfsgen۰CompressedFileInfo{
name: "traits.yaml",
modTime: time.Time{},
- uncompressedSize: 49570,
+ uncompressedSize: 49341,
- compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x5b\xb9\x91\xe0\xef\xf3\x57\xa0\xb4\x57\x65\x49\x45\x52\x9e\xc9\x26\x3b\xa7\xbb\xd9\x94\xc6\x76\x12\xcd\xf8\x43\x67\x3b\xb3\x97\x9a\x9b\x0a\xc1\xf7\x9a\x24\xcc\x47\xe0\x05\xc0\x93\xcc\xdc\xde\xff\x7e\x85\xee\xc6\xc7\x7b\x24\x25\xca\xb6\x66\xa3\xad\xdd\x54\xed\x58\xd2\x03\xd0\x68\x34\xfa\xbb\x1b\xde\x4a\xe5\xdd\xf9\x57\x63\xa1\xe5\x1a\xce\x85\x9c\xcf\x95\x56\x7e\xf3\x95\x10\x6d\x23\xfd\xdc\xd8\xf5\xb9\x [...]
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x5b\xb9\x91\xe0\xef\xf3\x57\xa0\xb4\x57\x65\x49\x45\x52\x9e\xc9\x26\x3b\xa7\xbb\xd9\x94\xc6\x76\x12\xcd\xf8\x43\x67\x3b\xb3\x97\x9a\x9b\x0a\xc1\xf7\x9a\x24\xcc\x47\xe0\x05\xc0\x93\xcc\xdc\xde\xff\x7e\x85\xee\xc6\xc7\x7b\x24\x25\xca\xb6\x66\xa3\xad\xdd\x54\xed\x58\xd2\x03\xd0\x68\x34\xfa\xbb\x1b\xde\x4a\xe5\xdd\xf9\x57\x63\xa1\xe5\x1a\xce\x85\x9c\xcf\x95\x56\x7e\xf3\x95\x10\x6d\x23\xfd\xdc\xd8\xf5\xb9\x [...]
},
}
fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go
index 67cdb79..7735a37 100644
--- a/pkg/trait/deployer.go
+++ b/pkg/trait/deployer.go
@@ -17,22 +17,6 @@ limitations under the License.
package trait
-import (
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "strings"
-
- k8serrors "k8s.io/apimachinery/pkg/api/errors"
- "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
- "k8s.io/apimachinery/pkg/types"
-
- ctrl "sigs.k8s.io/controller-runtime/pkg/client"
-
- "github.com/apache/camel-k/pkg/util/patch"
-)
-
// The deployer trait is responsible for deploying the resources owned by the integration, and can be used
// to explicitly select the underlying controller that will manage the integration pods.
//
@@ -45,8 +29,6 @@ type deployerTrait struct {
var _ ControllerStrategySelector = &deployerTrait{}
-var hasServerSideApply = true
-
func newDeployerTrait() Trait {
return &deployerTrait{
BaseTrait: NewBaseTrait("deployer", 900),
@@ -60,28 +42,9 @@ func (t *deployerTrait) Configure(e *Environment) (bool, error) {
func (t *deployerTrait) Apply(e *Environment) error {
// Register a post action that patches the resources generated by the traits
e.PostActions = append(e.PostActions, func(env *Environment) error {
+ applier := e.Client.ServerOrClientSideApplier()
for _, resource := range env.Resources.Items() {
- // We assume that server-side apply is enabled by default.
- // It is currently convoluted to check pro-actively whether server-side apply
- // is enabled. This is possible to fetch the OpenAPI endpoint, which returns
- // the entire server API document, then lookup the resource PATCH endpoint, and
- // check its list of accepted MIME types.
- // As a simpler solution, we fall back to client-side apply at the first
- // 415 error, and assume server-side apply is not available globally.
- if hasServerSideApply {
- err := t.serverSideApply(env, resource)
- switch {
- case err == nil:
- continue
- case isIncompatibleServerError(err):
- t.L.Info("Fallback to client-side apply to patch resources")
- hasServerSideApply = false
- default:
- // Keep server-side apply unless server is incompatible with it
- return err
- }
- }
- if err := t.clientSideApply(env, resource); err != nil {
+ if err := applier.Apply(e.Ctx, resource); err != nil {
return err
}
}
@@ -91,73 +54,6 @@ func (t *deployerTrait) Apply(e *Environment) error {
return nil
}
-func (t *deployerTrait) serverSideApply(env *Environment, resource ctrl.Object) error {
- target, err := patch.PositiveApplyPatch(resource)
- if err != nil {
- return err
- }
- err = env.Client.Patch(env.Ctx, target, ctrl.Apply, ctrl.ForceOwnership, ctrl.FieldOwner("camel-k-operator"))
- if err != nil {
- return fmt.Errorf("error during apply resource: %s/%s: %w", resource.GetNamespace(), resource.GetName(), err)
- }
- // Update the resource with the response returned from the API server
- return t.unstructuredToRuntimeObject(target, resource)
-}
-
-func (t *deployerTrait) clientSideApply(env *Environment, resource ctrl.Object) error {
- err := env.Client.Create(env.Ctx, resource)
- if err == nil {
- return nil
- } else if !k8serrors.IsAlreadyExists(err) {
- return fmt.Errorf("error during create resource: %s/%s: %w", resource.GetNamespace(), resource.GetName(), err)
- }
- object := &unstructured.Unstructured{}
- object.SetNamespace(resource.GetNamespace())
- object.SetName(resource.GetName())
- object.SetGroupVersionKind(resource.GetObjectKind().GroupVersionKind())
- err = env.Client.Get(env.Ctx, ctrl.ObjectKeyFromObject(object), object)
- if err != nil {
- return err
- }
- p, err := patch.PositiveMergePatch(object, resource)
- if err != nil {
- return err
- } else if len(p) == 0 {
- // Update the resource with the object returned from the API server
- return t.unstructuredToRuntimeObject(object, resource)
- }
- err = env.Client.Patch(env.Ctx, resource, ctrl.RawPatch(types.MergePatchType, p))
- if err != nil {
- return fmt.Errorf("error during patch %s/%s: %w", resource.GetNamespace(), resource.GetName(), err)
- }
- return nil
-}
-
-func (t *deployerTrait) unstructuredToRuntimeObject(u *unstructured.Unstructured, obj ctrl.Object) error {
- data, err := json.Marshal(u)
- if err != nil {
- return err
- }
- return json.Unmarshal(data, obj)
-}
-
-func isIncompatibleServerError(err error) bool {
- // First simpler check for older servers (i.e. OpenShift 3.11)
- if strings.Contains(err.Error(), "415: Unsupported Media Type") {
- return true
- }
-
- // 415: Unsupported media type means we're talking to a server which doesn't
- // support server-side apply.
- var serr *k8serrors.StatusError
- if errors.As(err, &serr) {
- return serr.Status().Code == http.StatusUnsupportedMediaType
- }
-
- // Non-StatusError means the error isn't because the server is incompatible.
- return false
-}
-
func (t *deployerTrait) SelectControllerStrategy(e *Environment) (*ControllerStrategy, error) {
if IsFalse(t.Enabled) {
return nil, nil
diff --git a/pkg/util/test/client.go b/pkg/util/test/client.go
index b4f6db4..7086e05 100644
--- a/pkg/util/test/client.go
+++ b/pkg/util/test/client.go
@@ -19,6 +19,7 @@ package test
import (
"context"
+ "fmt"
"strings"
"github.com/apache/camel-k/pkg/apis"
@@ -27,6 +28,7 @@ import (
fakecamelclientset "github.com/apache/camel-k/pkg/client/camel/clientset/versioned/fake"
camelv1 "github.com/apache/camel-k/pkg/client/camel/clientset/versioned/typed/camel/v1"
camelv1alpha1 "github.com/apache/camel-k/pkg/client/camel/clientset/versioned/typed/camel/v1alpha1"
+ autoscalingv1 "k8s.io/api/autoscaling/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -36,6 +38,9 @@ import (
fakeclientset "k8s.io/client-go/kubernetes/fake"
clientscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
+ "k8s.io/client-go/scale"
+ fakescale "k8s.io/client-go/scale/fake"
+ "k8s.io/client-go/testing"
controller "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
@@ -57,11 +62,44 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
clientset := fakeclientset.NewSimpleClientset(filterObjects(scheme, initObjs, func(gvk schema.GroupVersionKind) bool {
return !strings.Contains(gvk.Group, "camel") && !strings.Contains(gvk.Group, "knative")
})...)
+ replicasCount := make(map[string]int32)
+ fakescaleclient := fakescale.FakeScaleClient{}
+ fakescaleclient.AddReactor("update", "*", func(rawAction testing.Action) (handled bool, ret runtime.Object, err error) {
+ action := rawAction.(testing.UpdateAction) // nolint: forcetypeassert
+ obj := action.GetObject().(*autoscalingv1.Scale) // nolint: forcetypeassert
+ replicas := obj.Spec.Replicas
+ key := fmt.Sprintf("%s:%s:%s/%s", action.GetResource().Group, action.GetResource().Resource, action.GetNamespace(), obj.GetName())
+ replicasCount[key] = replicas
+ return true, &autoscalingv1.Scale{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: obj.Name,
+ Namespace: action.GetNamespace(),
+ },
+ Spec: autoscalingv1.ScaleSpec{
+ Replicas: replicas,
+ },
+ }, nil
+ })
+ fakescaleclient.AddReactor("get", "*", func(rawAction testing.Action) (handled bool, ret runtime.Object, err error) {
+ action := rawAction.(testing.GetAction) // nolint: forcetypeassert
+ key := fmt.Sprintf("%s:%s:%s/%s", action.GetResource().Group, action.GetResource().Resource, action.GetNamespace(), action.GetName())
+ obj := &autoscalingv1.Scale{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: action.GetName(),
+ Namespace: action.GetNamespace(),
+ },
+ Spec: autoscalingv1.ScaleSpec{
+ Replicas: replicasCount[key],
+ },
+ }
+ return true, obj, nil
+ })
return &FakeClient{
Client: c,
Interface: clientset,
camel: camelClientset,
+ scales: &fakescaleclient,
}, nil
}
@@ -82,7 +120,8 @@ func filterObjects(scheme *runtime.Scheme, input []runtime.Object, filter func(g
type FakeClient struct {
controller.Client
kubernetes.Interface
- camel camel.Interface
+ camel camel.Interface
+ scales *fakescale.FakeScaleClient
}
func (c *FakeClient) CamelV1() camelv1.CamelV1Interface {
@@ -123,6 +162,10 @@ func (c *FakeClient) ServerOrClientSideApplier() client.ServerOrClientSideApplie
}
}
+func (c *FakeClient) ScalesClient() (scale.ScalesGetter, error) {
+ return c.scales, nil
+}
+
type FakeDiscovery struct {
discovery.DiscoveryInterface
}
diff --git a/resources/traits.yaml b/resources/traits.yaml
index 638418d..fd24ebe 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -593,10 +593,6 @@ traits:
type: bool
description: Enables automatic configuration of the trait. Allows the trait to
infer KEDA triggers from the Kamelets.
- - name: camel-case-conversion
- type: bool
- description: Convert metadata properties to camelCase (needed because Camel K
- trait properties use kebab-case from command line). Disabled by default.
- name: hack-controller-replicas
type: bool
description: Set the spec->replicas field on the top level controller to an explicit