This is an automated email from the ASF dual-hosted git repository. lburgazzoli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 2372774192ebb9a464cc08e1b04255b580b970e5 Author: nferraro <ni.ferr...@gmail.com> AuthorDate: Thu Jun 20 13:05:05 2019 +0200 fix #693: add e2e tests --- Gopkg.lock | 40 +++ .../build_test.go | 40 ++- e2e/files/Java.java | 28 ++ e2e/files/groovy.groovy | 23 ++ e2e/files/js.js | 21 ++ e2e/files/kotlin.kts | 23 ++ e2e/files/xml.xml | 33 +++ e2e/install_test.go | 64 +++++ e2e/run_test.go | 78 ++++++ e2e/test_support.go | 297 +++++++++++++++++++++ go.mod | 4 +- pkg/apis/camel/v1alpha1/build_types_support.go | 27 ++ pkg/cmd/install.go | 6 +- pkg/util/openshift/register.go | 2 + test/builder_integration_test.go | 134 ---------- test/log_scrape_integration_test.go | 108 -------- test/testing_env.go | 181 ------------- 17 files changed, 668 insertions(+), 441 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 5f290cc..f5f1eac 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -443,6 +443,27 @@ version = "1.0.1" [[projects]] + digest = "1:9f353a779b8b118229dfc1541e41d72d1a3a6f2d13756f5fe66daeb0f52191ab" + name = "github.com/onsi/gomega" + packages = [ + ".", + "format", + "internal/assertion", + "internal/asyncassertion", + "internal/oraclematcher", + "internal/testingtsupport", + "matchers", + "matchers/support/goraph/bipartitegraph", + "matchers/support/goraph/edge", + "matchers/support/goraph/node", + "matchers/support/goraph/util", + "types", + ] + pruneopts = "NT" + revision = "90e289841c1ed79b7a598a7cd9959750cb5e89e2" + version = "v1.5.0" + +[[projects]] digest = "1:8bc8f43d2332d035857c92581df240f247c287629d5f60c751df609f9b6215c5" name = "github.com/openshift/api" packages = [ @@ -453,6 +474,7 @@ "image/dockerpre012", "image/v1", "pkg/serialization", + "project/v1", "route/v1", "template/v1", ] @@ -681,6 +703,9 @@ packages = [ "context", "context/ctxhttp", + "html", + "html/atom", + "html/charset", "http/httpguts", "http2", "http2/hpack", @@ -720,12 +745,24 @@ packages = [ "collate", "collate/build", + "encoding", + "encoding/charmap", + "encoding/htmlindex", + "encoding/internal", + "encoding/internal/identifier", + "encoding/japanese", + "encoding/korean", + "encoding/simplifiedchinese", + "encoding/traditionalchinese", + "encoding/unicode", "internal/colltab", "internal/gen", "internal/tag", "internal/triegen", "internal/ucd", + "internal/utf8internal", "language", + "runes", "secure/bidirule", "transform", "unicode/bidi", @@ -1104,15 +1141,18 @@ "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1", "github.com/fatih/structs", "github.com/go-logr/logr", + "github.com/google/uuid", "github.com/jpillora/backoff", "github.com/knative/eventing/pkg/apis/eventing/v1alpha1", "github.com/knative/pkg/apis/duck/v1alpha1", "github.com/knative/serving/pkg/apis/serving/v1alpha1", "github.com/mitchellh/mapstructure", + "github.com/onsi/gomega", "github.com/openshift/api/apps/v1", "github.com/openshift/api/authorization/v1", "github.com/openshift/api/build/v1", "github.com/openshift/api/image/v1", + "github.com/openshift/api/project/v1", "github.com/openshift/api/route/v1", "github.com/openshift/api/template/v1", "github.com/operator-framework/operator-sdk/pkg/k8sutil", diff --git a/test/cluster_integration_test.go b/e2e/build_test.go similarity index 53% rename from test/cluster_integration_test.go rename to e2e/build_test.go index d18aa72..2b8aa5d 100644 --- a/test/cluster_integration_test.go +++ b/e2e/build_test.go @@ -19,25 +19,39 @@ See the License for the specific language governing permissions and limitations under the License. */ -package test +package e2e import ( "testing" + "time" - "github.com/apache/camel-k/pkg/install" - "github.com/stretchr/testify/assert" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + . "github.com/onsi/gomega" ) -func TestInstallation(t *testing.T) { - installedCtxCRD, err := install.IsCRDInstalled(testContext, testClient, "IntegrationKit") - assert.Nil(t, err) - assert.True(t, installedCtxCRD) +func TestKitJVMFullBuild(t *testing.T) { + doNamedKitFullBuild(t, "jvm") +} + +func TestKitGroovyFullBuild(t *testing.T) { + doNamedKitFullBuild(t, "groovy") +} - installedCRD, err := install.IsCRDInstalled(testContext, testClient, "Integration") - assert.Nil(t, err) - assert.True(t, installedCRD) +func TestKitKotlinFullBuild(t *testing.T) { + doNamedKitFullBuild(t, "kotlin") +} + +func TestKitHealthFullBuild(t *testing.T) { + doNamedKitFullBuild(t, "knative") +} - installedClusterRole, err := install.IsClusterRoleInstalled(testContext, testClient) - assert.Nil(t, err) - assert.True(t, installedClusterRole) +func doNamedKitFullBuild(t *testing.T, name string) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns, "--kit", name).Execute()).Should(BeNil()) + Eventually(build(ns, name)).ShouldNot(BeNil()) + Eventually(func() v1alpha1.BuildPhase { + return build(ns, name)().Status.Phase + }, 5*time.Minute).Should(Equal(v1alpha1.BuildPhaseSucceeded)) + }) } diff --git a/e2e/files/Java.java b/e2e/files/Java.java new file mode 100644 index 0000000..f586b60 --- /dev/null +++ b/e2e/files/Java.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import org.apache.camel.builder.RouteBuilder; + +public class Java extends RouteBuilder { + @Override + public void configure() throws Exception { + from("timer:tick") + .setHeader("m").constant("string!") + .setBody().simple("Magic${header.m}") + .log("${body}"); + } +} \ No newline at end of file diff --git a/e2e/files/groovy.groovy b/e2e/files/groovy.groovy new file mode 100644 index 0000000..fdfa153 --- /dev/null +++ b/e2e/files/groovy.groovy @@ -0,0 +1,23 @@ +/* + * 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. + */ + +from('timer:groovy?period=1s') + .routeId('groovy') + .setHeader("m").constant("string!") + .setBody() + .simple('Magic${header.m}') + .to('log:info?showAll=false') diff --git a/e2e/files/js.js b/e2e/files/js.js new file mode 100644 index 0000000..99aaf74 --- /dev/null +++ b/e2e/files/js.js @@ -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. + +from('timer:js?period=1s') + .routeId('js') + .setHeader("m").constant("string!") + .setBody() + .simple('Magic${header.m}') + .to('log:info') \ No newline at end of file diff --git a/e2e/files/kotlin.kts b/e2e/files/kotlin.kts new file mode 100644 index 0000000..ea378fa --- /dev/null +++ b/e2e/files/kotlin.kts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +from("timer:kotlin?period=1s") + .routeId("kotlin") + .setHeader("m").constant("string!") + .setBody() + .simple("Magic\${header.m}") + .to("log:info") diff --git a/e2e/files/xml.xml b/e2e/files/xml.xml new file mode 100644 index 0000000..a656351 --- /dev/null +++ b/e2e/files/xml.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://camel.apache.org/schema/spring" + xsi:schemaLocation=" + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <route id="hello"> + <from uri="timer:hello?period=3s"/> + <setHeader headerName="m"> + <constant>string!</constant> + </setHeader> + <setBody> + <simple>Magic${header.m}</simple> + </setBody> + <to uri="log:info"/> + </route> + +</routes> diff --git a/e2e/install_test.go b/e2e/install_test.go new file mode 100644 index 0000000..53cf830 --- /dev/null +++ b/e2e/install_test.go @@ -0,0 +1,64 @@ +// +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 e2e + +import ( + "testing" + + . "github.com/onsi/gomega" +) + +func TestBasicInstallation(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns).Execute()).Should(BeNil()) + Eventually(operatorPod(ns)).ShouldNot(BeNil()) + }) +} + +func TestAlternativeImageInstallation(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns, "--operatorPod-image", "x/y:latest").Execute()).Should(BeNil()) + Eventually(operatorImage(ns)).Should(Equal("x/y:latest")) + }) +} + +func TestKitJVMInstallation(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns, "--kit", "jvm").Execute()).Should(BeNil()) + Eventually(build(ns, "jvm")).ShouldNot(BeNil()) + }) +} + +func TestMavenRepositoryInstallation(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns, "--maven-repository", "https://my.repo.org/public/").Execute()).Should(BeNil()) + Eventually(configmap(ns, "camel-k-maven-settings")).Should(Not(BeNil())) + Eventually(func()string { + return configmap(ns, "camel-k-maven-settings")().Data["settings.xml"] + }).Should(ContainSubstring("https://my.repo.org/public/")) + }) +} + diff --git a/e2e/run_test.go b/e2e/run_test.go new file mode 100644 index 0000000..550a685 --- /dev/null +++ b/e2e/run_test.go @@ -0,0 +1,78 @@ +// +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 e2e + +import ( + "testing" + "time" + + . "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" +) + +func TestRunSimpleExamples(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns).Execute()).Should(BeNil()) + + t.Run("run java", func(t *testing.T) { + RegisterTestingT(t) + Expect(kamel("run", "-n", ns, "files/Java.java").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "java"), 5*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "java"), 1*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + + t.Run("run xml", func(t *testing.T) { + RegisterTestingT(t) + Expect(kamel("run", "-n", ns, "files/xml.xml").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "xml"), 5*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "xml"), 1*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + + t.Run("run groovy", func(t *testing.T) { + RegisterTestingT(t) + Expect(kamel("run", "-n", ns, "files/groovy.groovy").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "groovy"), 5*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "groovy"), 1*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + + t.Run("run js", func(t *testing.T) { + RegisterTestingT(t) + Expect(kamel("run", "-n", ns, "files/js.js").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "js"), 5*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "js"), 1*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + + t.Run("run kotlin", func(t *testing.T) { + RegisterTestingT(t) + Expect(kamel("run", "-n", ns, "files/kotlin.kts").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "kotlin"), 5*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "kotlin"), 1*time.Minute).Should(ContainSubstring("Magicstring!")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) + + }) +} diff --git a/e2e/test_support.go b/e2e/test_support.go new file mode 100644 index 0000000..7ee58a5 --- /dev/null +++ b/e2e/test_support.go @@ -0,0 +1,297 @@ +// +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 e2e + +import ( + "context" + "time" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/cmd" + "github.com/apache/camel-k/pkg/util/log" + "github.com/apache/camel-k/pkg/util/openshift" + "github.com/google/uuid" + "github.com/onsi/gomega" + projectv1 "github.com/openshift/api/project/v1" + "github.com/spf13/cobra" + "io/ioutil" + v1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" +) + +var testContext context.Context +var testClient client.Client + +func init() { + var err error + testContext = context.TODO() + testClient, err = newTestClient() + if err != nil { + panic(err) + } + + // Defaults for testing + gomega.SetDefaultEventuallyTimeout(10 * time.Second) +} + +func newTestClient() (client.Client, error) { + return client.NewOutOfClusterClient("") +} + +func kamel(args ...string) *cobra.Command { + c, err := cmd.NewKamelCommand(testContext) + if err != nil { + panic(err) + } + c.SetArgs(args) + return c +} + +/* + Curryied utility functions for testing +*/ + +func integrationLogs(ns string, name string) func() string { + return func() string { + pod := integrationPod(ns, name)() + if pod == nil { + return "" + } + containerName := "" + if len(pod.Spec.Containers) > 1 { + containerName = pod.Spec.Containers[0].Name + } + tail := int64(100) + logOptions := v1.PodLogOptions{ + Follow: false, + Container: containerName, + TailLines: &tail, + } + byteReader, err := testClient.CoreV1().Pods(ns).GetLogs(pod.Name, &logOptions).Context(testContext).Stream() + if err != nil { + log.Error(err, "Error while reading the pod logs") + return "" + } + defer func() { + if err := byteReader.Close(); err != nil { + log.Error(err, "Error closing the stream") + } + }() + + bytes, err := ioutil.ReadAll(byteReader) + if err != nil { + log.Error(err, "Error while reading the pod logs content") + return "" + } + return string(bytes) + } +} + +func integrationPodPhase(ns string, name string) func() v1.PodPhase { + return func() v1.PodPhase { + pod := integrationPod(ns, name)() + if pod == nil { + return "" + } + return pod.Status.Phase + } +} + +func integrationPod(ns string, name string) func() *v1.Pod { + return func() *v1.Pod { + lst := v1.PodList{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } + opts := k8sclient.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{ + "camel.apache.org/integration": name, + }), + Namespace: ns, + } + if err := testClient.List(testContext, &opts, &lst); err != nil { + panic(err) + } + if len(lst.Items) == 0 { + return nil + } + return &lst.Items[0] + } +} + +func operatorImage(ns string) func() string { + return func() string { + pod := operatorPod(ns)() + if pod != nil { + if len(pod.Spec.Containers) > 0 { + return pod.Spec.Containers[0].Image + } + } + return "" + } +} + +func configmap(ns string, name string) func() *v1.ConfigMap { + return func() *v1.ConfigMap { + cm := v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: metav1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + } + key := k8sclient.ObjectKey{ + Namespace: ns, + Name: name, + } + if err := testClient.Get(testContext, key, &cm); err != nil && k8serrors.IsNotFound(err) { + return nil + } else if err != nil { + log.Error(err, "Error while retrieving configmap "+name) + return nil + } + return &cm + } +} + +func build(ns string, name string) func() *v1alpha1.Build { + return func() *v1alpha1.Build { + build := v1alpha1.NewBuild(ns, name) + key := k8sclient.ObjectKey{ + Namespace: ns, + Name: name, + } + if err := testClient.Get(testContext, key, &build); err != nil && k8serrors.IsNotFound(err) { + return nil + } else if err != nil { + log.Error(err, "Error while retrieving build "+name) + return nil + } + return &build + } +} + +func operatorPod(ns string) func() *v1.Pod { + return func() *v1.Pod { + lst := v1.PodList{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: v1.SchemeGroupVersion.String(), + }, + } + opts := k8sclient.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{ + "camel.apache.org/component": "operatorPod", + }), + Namespace: ns, + } + if err := testClient.List(testContext, &opts, &lst); err != nil { + panic(err) + } + if len(lst.Items) == 0 { + return nil + } + return &lst.Items[0] + } +} + +/* + Namespace testing functions +*/ + +func withNewTestNamespace(doRun func(string)) { + ns := newTestNamespace() + defer deleteTestNamespace(ns) + + doRun(ns.GetName()) +} + +func deleteTestNamespace(ns metav1.Object) { + var oc bool + var err error + if oc, err = openshift.IsOpenShift(testClient); err != nil { + panic(err) + } else if oc { + prj := &projectv1.Project{ + TypeMeta: metav1.TypeMeta{ + APIVersion: projectv1.SchemeGroupVersion.String(), + Kind: "Project", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: ns.GetName(), + }, + } + if err := testClient.Delete(testContext, prj); err != nil { + log.Error(err, "cannot delete test project", "name", prj.Name) + } + } else { + if err := testClient.Delete(testContext, ns.(runtime.Object)); err != nil { + log.Error(err, "cannot delete test namespace", "name", ns.GetName()) + } + } +} + +func newTestNamespace() metav1.Object { + var err error + var oc bool + var obj runtime.Object + + name := "test-" + uuid.New().String() + + if oc, err = openshift.IsOpenShift(testClient); err != nil { + panic(err) + } else if oc { + obj = &projectv1.ProjectRequest{ + TypeMeta: metav1.TypeMeta{ + APIVersion: projectv1.SchemeGroupVersion.String(), + Kind: "ProjectRequest", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + } else { + obj = &v1.Namespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Namespace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + } + if err = testClient.Create(testContext, obj); err != nil { + panic(err) + } + return obj.(metav1.Object) +} diff --git a/go.mod b/go.mod index 265309f..be5c294 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect github.com/google/go-containerregistry v0.0.0-20190206233756-dbc4da98389f // indirect github.com/google/gofuzz v1.0.0 // indirect - github.com/google/uuid v1.1.0 // indirect + github.com/google/uuid v1.1.0 github.com/googleapis/gnostic v0.2.0 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect github.com/imdario/mergo v0.3.7 // indirect @@ -36,7 +36,7 @@ require ( github.com/mitchellh/mapstructure v1.1.2 github.com/modern-go/reflect2 v1.0.1 // indirect github.com/onsi/ginkgo v1.8.0 // indirect - github.com/onsi/gomega v1.5.0 // indirect + github.com/onsi/gomega v1.5.0 github.com/openshift/api v3.9.0+incompatible github.com/operator-framework/operator-sdk v0.8.0 github.com/pborman/uuid v1.2.0 // indirect diff --git a/pkg/apis/camel/v1alpha1/build_types_support.go b/pkg/apis/camel/v1alpha1/build_types_support.go new file mode 100644 index 0000000..d70be26 --- /dev/null +++ b/pkg/apis/camel/v1alpha1/build_types_support.go @@ -0,0 +1,27 @@ +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// NewBuild -- +func NewBuild(namespace string, name string) Build { + return Build{ + TypeMeta: metav1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: BuildKind, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + } +} + +// NewBuildList -- +func NewBuildList() BuildList { + return BuildList{ + TypeMeta: metav1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: BuildKind, + }, + } +} diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 0135156..f7e21a3 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -373,7 +373,7 @@ func (o *installCmdOptions) validate(_ *cobra.Command, _ []string) error { return result } -func errorIfKitIsNotAvailable(schema *runtime.Scheme, context string) error { +func errorIfKitIsNotAvailable(schema *runtime.Scheme, kit string) error { for _, resource := range deploy.Resources { resource, err := kubernetes.LoadResourceFromYaml(schema, resource) if err != nil { @@ -385,11 +385,11 @@ func errorIfKitIsNotAvailable(schema *runtime.Scheme, context string) error { continue } integrationKit := resource.(*v1alpha1.IntegrationKit) - if integrationKit.Name == context { + if integrationKit.Name == kit { return nil } } - return errors.Errorf("Unknown context '%s'", context) + return errors.Errorf("Unknown kit '%s'", kit) } func decodeMavenSettings(mavenSettings string) (v1alpha1.ValueSource, error) { diff --git a/pkg/util/openshift/register.go b/pkg/util/openshift/register.go index c089046..b347a5c 100644 --- a/pkg/util/openshift/register.go +++ b/pkg/util/openshift/register.go @@ -23,6 +23,7 @@ import ( authorization "github.com/openshift/api/authorization/v1" build "github.com/openshift/api/build/v1" image "github.com/openshift/api/image/v1" + project "github.com/openshift/api/project/v1" route "github.com/openshift/api/route/v1" template "github.com/openshift/api/template/v1" "k8s.io/apimachinery/pkg/runtime" @@ -42,6 +43,7 @@ func AddToScheme(scheme *runtime.Scheme) error { err = doAdd(route.AddToScheme, scheme, err) err = doAdd(build.AddToScheme, scheme, err) err = doAdd(authorization.AddToScheme, scheme, err) + err = doAdd(project.AddToScheme, scheme, err) return err } diff --git a/test/builder_integration_test.go b/test/builder_integration_test.go deleted file mode 100644 index 6fddfc7..0000000 --- a/test/builder_integration_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// +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 test - -import ( - "context" - "testing" - "time" - - "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" - "github.com/apache/camel-k/pkg/builder" - _ "github.com/apache/camel-k/pkg/builder/kaniko" - "github.com/apache/camel-k/pkg/builder/s2i" - "github.com/apache/camel-k/pkg/util/defaults" - "github.com/apache/camel-k/pkg/util/test" - - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/stretchr/testify/assert" -) - -func TestBuildManagerBuild(t *testing.T) { - b := builder.New(testClient) - - catalog, err := test.DefaultCatalog() - assert.Nil(t, err) - - err = testClient.Create(context.TODO(), &v1alpha1.CamelCatalog{ - ObjectMeta: metav1.ObjectMeta{ - Name: "catalog-test", - Namespace: getTargetNamespace(), - }, - Spec: catalog.CamelCatalogSpec, - }) - if err != nil && !k8serrors.IsAlreadyExists(err) { - assert.Error(t, err) - } - - r := v1alpha1.BuildSpec{ - RuntimeVersion: defaults.RuntimeVersion, - Meta: metav1.ObjectMeta{ - Name: "man-test", - Namespace: getTargetNamespace(), - ResourceVersion: "1", - }, - Platform: v1alpha1.IntegrationPlatformSpec{ - Build: v1alpha1.IntegrationPlatformBuildSpec{ - CamelVersion: catalog.Version, - RuntimeVersion: defaults.RuntimeVersion, - BaseImage: "docker.io/fabric8/s2i-java:3.0-java8", - Timeout: metav1.Duration{ - Duration: 5 * time.Minute, - }, - }, - }, - Dependencies: []string{ - "mvn:org.apache.camel/camel-core", - "camel:telegram", - }, - Steps: builder.StepIDsFor(s2i.DefaultSteps...), - } - - result := b.Build(r) - - assert.NotEqual(t, v1alpha1.BuildPhaseFailed, result.Phase) - assert.Equal(t, v1alpha1.BuildPhaseSucceeded, result.Phase) - assert.Regexp(t, ".*/.*/.*:.*", result.Image) -} - -func TestBuildManagerFailedBuild(t *testing.T) { - b := builder.New(testClient) - - catalog, err := test.DefaultCatalog() - assert.Nil(t, err) - - err = testClient.Create(context.TODO(), &v1alpha1.CamelCatalog{ - ObjectMeta: metav1.ObjectMeta{ - Name: "catalog-test", - Namespace: getTargetNamespace(), - }, - Spec: catalog.CamelCatalogSpec, - }) - if err != nil && !k8serrors.IsAlreadyExists(err) { - assert.Error(t, err) - } - - r := v1alpha1.BuildSpec{ - RuntimeVersion: defaults.RuntimeVersion, - Meta: metav1.ObjectMeta{ - Name: "man-test", - Namespace: getTargetNamespace(), - ResourceVersion: "1", - }, - Platform: v1alpha1.IntegrationPlatformSpec{ - Build: v1alpha1.IntegrationPlatformBuildSpec{ - CamelVersion: catalog.Version, - RuntimeVersion: defaults.RuntimeVersion, - BaseImage: "docker.io/fabric8/s2i-java:3.0-java8", - Timeout: metav1.Duration{ - Duration: 5 * time.Minute, - }, - }, - }, - Dependencies: []string{ - "mvn:org.apache.camel/camel-cippalippa", - }, - Steps: builder.StepIDsFor(s2i.DefaultSteps...), - } - - result := b.Build(r) - - assert.Equal(t, v1alpha1.BuildPhaseFailed, result.Phase) - assert.NotEqual(t, v1alpha1.BuildPhaseSucceeded, result.Phase) -} diff --git a/test/log_scrape_integration_test.go b/test/log_scrape_integration_test.go deleted file mode 100644 index 2124982..0000000 --- a/test/log_scrape_integration_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// +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 test - -import ( - "context" - "strings" - "testing" - "time" - - "github.com/apache/camel-k/pkg/util/kubernetes/log" - "github.com/stretchr/testify/assert" -) - -func TestPodLogScrape(t *testing.T) { - token := "Hello Camel K!" - pod, err := createDummyPod("scraped", "/bin/sh", "-c", "for i in `seq 1 50`; do echo \""+token+"\" && sleep 2; done") - defer testClient.Delete(testContext, pod) - assert.Nil(t, err) - - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(30*time.Second)) - defer cancel() - scraper := log.NewPodScraper(testClient, pod.Namespace, pod.Name, "scraped") - in := scraper.Start(ctx) - - res := make(chan bool) - go func() { - for { - if dl, _ := ctx.Deadline(); time.Now().After(dl) { - return - } - - str, _ := in.ReadString('\n') - if strings.Contains(str, token) { - res <- true - return - } - } - }() - - select { - case <-res: - break - case <-time.After(30 * time.Second): - assert.Fail(t, "timeout while waiting from token") - } -} - -func TestSelectorLogScrape(t *testing.T) { - token := "Hello Camel K!" - replicas := int32(3) - deployment, err := createDummyDeployment("scraped-deployment", &replicas, "scrape", "me", "/bin/sh", "-c", "for i in `seq 1 50`; do echo \""+token+"\" && sleep 2; done") - defer testClient.Delete(testContext, deployment) - assert.Nil(t, err) - - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(30*time.Second)) - defer cancel() - scraper := log.NewSelectorScraper(testClient, deployment.Namespace, "main", "scrape=me") - in := scraper.Start(ctx) - - res := make(chan string) - go func() { - for { - if dl, _ := ctx.Deadline(); time.Now().After(dl) { - return - } - - str, _ := in.ReadString('\n') - if strings.Contains(str, token) { - res <- str[0:3] - } - } - }() - - recv := make(map[string]bool) -loop: - for { - select { - case r := <-res: - recv[r] = true - if len(recv) == 3 { - break loop - } - case <-time.After(13 * time.Second): - assert.Fail(t, "timeout while waiting from token") - break loop - } - } -} diff --git a/test/testing_env.go b/test/testing_env.go deleted file mode 100644 index 0db5b58..0000000 --- a/test/testing_env.go +++ /dev/null @@ -1,181 +0,0 @@ -// +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 test - -import ( - "context" - "time" - - "k8s.io/apimachinery/pkg/labels" - - "github.com/apache/camel-k/pkg/client" - "github.com/apache/camel-k/pkg/install" - appsv1 "k8s.io/api/apps/v1" - v1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sclient "sigs.k8s.io/controller-runtime/pkg/client" -) - -var testContext context.Context -var testClient client.Client - -func newTestClient() (client.Client, error) { - return client.NewOutOfClusterClient("") -} - -func init() { - var err error - err = install.SetupClusterwideResources(testContext, client.Provider{Get: newTestClient}) - if err != nil { - panic(err) - } - - testContext = context.TODO() - testClient, err = newTestClient() - if err != nil { - panic(err) - } - - cfg := install.OperatorConfiguration{ - Namespace: getTargetNamespace(), - } - - err = install.Operator(testContext, testClient, cfg) - if err != nil { - panic(err) - } -} - -func getTargetNamespace() string { - ns, err := client.GetCurrentNamespace("") - if err != nil { - panic(err) - } - return ns -} - -func createDummyDeployment(name string, replicas *int32, labelKey string, labelValue string, command ...string) (*appsv1.Deployment, error) { - deployment := getDummyDeployment(name, replicas, labelKey, labelValue, command...) - err := testClient.Delete(testContext, &deployment, k8sclient.GracePeriodSeconds(0)) - if err != nil && !k8serrors.IsNotFound(err) { - return nil, err - } - for { - list := v1.PodList{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: v1.SchemeGroupVersion.String(), - }, - } - options := k8sclient.ListOptions{ - Namespace: getTargetNamespace(), - LabelSelector: labels.SelectorFromSet(labels.Set{ - labelKey: labelValue, - }), - } - err := testClient.List(testContext, &options, &list) - if err != nil { - return nil, err - } - - if len(list.Items) > 0 { - time.Sleep(1 * time.Second) - } else { - break - } - } - err = testClient.Create(testContext, &deployment) - return &deployment, err -} - -func getDummyDeployment(name string, replicas *int32, labelKey string, labelValue string, command ...string) appsv1.Deployment { - return appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: getTargetNamespace(), - }, - Spec: appsv1.DeploymentSpec{ - Replicas: replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - labelKey: labelValue, - }, - }, - Template: v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - labelKey: labelValue, - }, - }, - Spec: getDummyPod(name, command...).Spec, - }, - }, - } -} - -func createDummyPod(name string, command ...string) (*v1.Pod, error) { - pod := getDummyPod(name, command...) - err := testClient.Delete(testContext, &pod, k8sclient.GracePeriodSeconds(0)) - if err != nil && !k8serrors.IsNotFound(err) { - return nil, err - } - for { - err := testClient.Create(testContext, &pod) - if err != nil && k8serrors.IsAlreadyExists(err) { - time.Sleep(1 * time.Second) - } else if err != nil { - return nil, err - } else { - break - } - } - return &pod, nil -} - -func getDummyPod(name string, command ...string) v1.Pod { - gracePeriod := int64(0) - return v1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: v1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: getTargetNamespace(), - Name: name, - }, - Spec: v1.PodSpec{ - TerminationGracePeriodSeconds: &gracePeriod, - Containers: []v1.Container{ - { - Name: name, - Image: "busybox", - Command: command, - }, - }, - }, - } -}