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 3a5060398e58114bade7febbc6661e98e13fa327 Author: nicolaferraro <ni.ferr...@gmail.com> AuthorDate: Mon Oct 18 15:50:35 2021 +0200 Fix #2687: add e2e tests --- e2e/common/secondary_platform_test.go | 74 +++++++++++++++++++++++++++++++++++ e2e/support/test_support.go | 53 ++++++++++++++++++++++++- pkg/cmd/run.go | 19 +++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/e2e/common/secondary_platform_test.go b/e2e/common/secondary_platform_test.go new file mode 100644 index 0000000..55ef6c4 --- /dev/null +++ b/e2e/common/secondary_platform_test.go @@ -0,0 +1,74 @@ +//go:build integration +// +build integration + +// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration" + +/* +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 common + +import ( + "testing" + + . "github.com/apache/camel-k/e2e/support" + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" +) + +func TestSecondaryPlatform(t *testing.T) { + WithNewTestNamespace(t, func(ns string) { + Expect(Kamel("install", "-n", ns).Execute()).To(Succeed()) + Expect(ConfigureSecondayPlatfromWith(ns, func(p *v1.IntegrationPlatform) { + p.Name = "secondary" + if p.Spec.Traits == nil { + p.Spec.Traits = make(map[string]v1.TraitSpec) + } + p.Spec.Traits["container"] = v1.TraitSpec{ + Configuration: AsTraitConfiguration(map[string]string{ + "limitCPU": "0.1", + }), + } + })).To(Succeed()) + + Expect(Kamel("run", "-n", ns, "--name", "limited", "--annotation", "camel.apache.org/platform.id=secondary", "files/yaml.yaml").Execute()).To(Succeed()) + + Eventually(IntegrationPod(ns, "limited"), TestTimeoutMedium).Should(Not(BeNil())) + Eventually(IntegrationPodHas(ns, "limited", func(pod *corev1.Pod) bool { + if len(pod.Spec.Containers) != 1 { + return false + } + cpuLimits := pod.Spec.Containers[0].Resources.Limits.Cpu() + return cpuLimits != nil && cpuLimits.AsApproximateFloat64() > 0 + }), TestTimeoutShort).Should(BeTrue()) + Expect(Kamel("delete", "limited", "-n", ns).Execute()).To(Succeed()) + + Expect(Kamel("run", "-n", ns, "--name", "normal", "files/yaml.yaml").Execute()).To(Succeed()) + Eventually(IntegrationPod(ns, "normal"), TestTimeoutShort).Should(Not(BeNil())) + Eventually(IntegrationPodHas(ns, "normal", func(pod *corev1.Pod) bool { + if len(pod.Spec.Containers) != 1 { + return false + } + cpuLimits := pod.Spec.Containers[0].Resources.Limits.Cpu() + return cpuLimits == nil || cpuLimits.IsZero() + }), TestTimeoutShort).Should(BeTrue()) + + // Clean up + Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed()) + }) +} diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go index 64dbf5c..13fbd02 100644 --- a/e2e/support/test_support.go +++ b/e2e/support/test_support.go @@ -37,6 +37,7 @@ import ( "testing" "time" + "github.com/apache/camel-k/pkg/platform" "github.com/google/uuid" "github.com/onsi/gomega" "github.com/pkg/errors" @@ -369,6 +370,16 @@ func IntegrationPod(ns string, name string) func() *corev1.Pod { } } +func IntegrationPodHas(ns string, name string, predicate func(pod *corev1.Pod) bool) func() bool { + return func() bool { + pod := IntegrationPod(ns, name)() + if pod == nil { + return false + } + return predicate(pod) + } +} + func IntegrationPods(ns string, name string) func() []corev1.Pod { return func() []corev1.Pod { lst := corev1.PodList{ @@ -1018,7 +1029,21 @@ func Platform(ns string) func() *v1.IntegrationPlatform { return nil } if len(lst.Items) > 1 { - panic("multiple integration platforms found in namespace " + ns) + var pl *v1.IntegrationPlatform + for _, p := range lst.Items { + p := p + if platform.IsSecondary(&p) { + continue + } + if pl != nil { + panic("multiple primary integration platforms found in namespace " + ns) + } + pl = &p + } + if pl == nil { + panic(fmt.Sprintf("multiple integration platforms found in namespace %q but no one is primary", ns)) + } + return pl } return &lst.Items[0] } @@ -1080,6 +1105,22 @@ func AssignPlatformToOperator(ns, operator string) error { return TestClient().Update(TestContext, pl) } +func ConfigureSecondayPlatfromWith(ns string, customizer func(pl *v1.IntegrationPlatform)) error { + pl := Platform(ns)() + if pl == nil { + return errors.New("cannot find primary platform") + } + if pl.Annotations == nil { + pl.Annotations = make(map[string]string) + } + pl.Annotations[v1.SecondaryPlatformAnnotation] = "true" + pl.ObjectMeta.ResourceVersion = "" + pl.Name = "" + pl.Status = v1.IntegrationPlatformStatus{} + customizer(pl) + return TestClient().Create(TestContext, pl) +} + func CRDs() func() []metav1.APIResource { return func() []metav1.APIResource { @@ -1509,6 +1550,16 @@ func asEndpointProperties(props map[string]string) *v1alpha1.EndpointProperties } } +func AsTraitConfiguration(props map[string]string) v1.TraitConfiguration { + bytes, err := json.Marshal(props) + if err != nil { + panic(err) + } + return v1.TraitConfiguration{ + RawMessage: bytes, + } +} + /* Namespace testing functions */ diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 45d755d..f7f4ba4 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -98,6 +98,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) cmd.Flags().StringArrayP("volume", "v", nil, "Mount a volume into the integration container. E.g \"-v pvcname:/container/path\"") cmd.Flags().StringArrayP("env", "e", nil, "Set an environment variable in the integration container. E.g \"-e MY_VAR=my-value\"") cmd.Flags().StringArray("property-file", nil, "[Deprecated] Bind a property file to the integration. E.g. \"--property-file integration.properties\"") + cmd.Flags().StringArray("annotation", nil, "Add an annotation to the integration. E.g. \"--annotation my.company=hello\"") cmd.Flags().StringArray("label", nil, "Add a label to the integration. E.g. \"--label my.company=hello\"") cmd.Flags().StringArray("source", nil, "Add source file to your integration, this is added to the list of files listed as arguments of the command") cmd.Flags().String("pod-template", "", "The path of the YAML file containing a PodSpec template to be used for the Integration pods") @@ -140,6 +141,7 @@ type runCmdOptions struct { // Deprecated: PropertyFiles has been deprecated in 1.5 PropertyFiles []string `mapstructure:"property-files" yaml:",omitempty"` Labels []string `mapstructure:"labels" yaml:",omitempty"` + Annotations []string `mapstructure:"annotations" yaml:",omitempty"` Sources []string `mapstructure:"sources" yaml:",omitempty"` } @@ -256,6 +258,13 @@ func (o *runCmdOptions) validate() error { } } + for _, annotation := range o.Annotations { + parts := strings.SplitN(annotation, "=", 2) + if len(parts) != 2 { + return fmt.Errorf(`invalid annotation specification %s. Expected "<annotationkey>=<annotationvalue>"`, annotation) + } + } + return nil } @@ -520,6 +529,16 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C } } + for _, annotation := range o.Annotations { + parts := strings.SplitN(annotation, "=", 2) + if len(parts) == 2 { + if integration.Annotations == nil { + integration.Annotations = make(map[string]string) + } + integration.Annotations[parts[0]] = parts[1] + } + } + srcs := make([]string, 0, len(sources)+len(o.Sources)) srcs = append(srcs, sources...) srcs = append(srcs, o.Sources...)