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 2021/04/12 13:59:40 UTC

[camel-k] branch master updated: Add OLM upgrade test

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c69a47  Add OLM upgrade test
8c69a47 is described below

commit 8c69a474ae7ab0148a476c494de7dccbcccc0757
Author: Jan <jb...@redhat.com>
AuthorDate: Wed Mar 10 18:01:03 2021 +0100

    Add OLM upgrade test
---
 .github/workflows/upgrade.yml        |  65 ++++++++++++--
 config/manifests/kustomization.yaml  |   1 +
 e2e/support/test_support.go          |  62 +++++++++++++
 e2e/upgrade/olm_upgrade_test.go      | 163 +++++++++++++++++++++++++++++++++++
 e2e/upgrade/upgrade_operator_test.go |  18 +++-
 5 files changed, 300 insertions(+), 9 deletions(-)

diff --git a/.github/workflows/upgrade.yml b/.github/workflows/upgrade.yml
index b3b2e2a..9f60642 100644
--- a/.github/workflows/upgrade.yml
+++ b/.github/workflows/upgrade.yml
@@ -64,9 +64,19 @@ jobs:
       with:
         version: "11"
     - name: Set Go
-      uses: actions/setup-go@v1
+      uses: actions/setup-go@v2
       with:
         go-version: 1.13.x
+    - name: Set up operator-sdk
+      run: |
+        curl -L https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/operator-sdk_linux_amd64 -o operator-sdk
+        chmod +x operator-sdk
+        sudo mv operator-sdk /usr/local/bin/
+    - name: Set up opm tool
+      run: |
+        curl -L https://github.com/operator-framework/operator-registry/releases/download/v1.16.1/linux-amd64-opm -o opm
+        chmod +x opm
+        sudo mv opm /usr/local/bin/
     - name: Kubernetes KinD Cluster
       uses: container-tools/kind-action@v1
       with:
@@ -75,6 +85,12 @@ jobs:
       run: |
         kubectl cluster-info
         kubectl describe nodes
+    - name: Install OLM
+      run: |
+        kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.17.0/crds.yaml
+        # wait for a while to be sure CRDs are installed
+        sleep 1
+        kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.17.0/olm.yaml
     - name: Get Kamel CLI
       run: |
         export KAMEL_VERSION=$(make get-last-released-version)
@@ -92,12 +108,52 @@ jobs:
         cp ./kamel ./build/_output/bin/
         echo "Building the images"
         export LOCAL_IMAGE=$KIND_REGISTRY/apache/camel-k:$(make get-version)
+        echo "LOCAL_IMAGE=${LOCAL_IMAGE}" >> $GITHUB_ENV
         docker build -t "${LOCAL_IMAGE}" -f build/Dockerfile .
         docker push ${LOCAL_IMAGE}
+    - name: Build Operator bundle
+      run: |
+        echo "Build Operator bundle"
+
+        # reinstall kustomize to be always on the same version
+        sudo rm $(which kustomize)
+
+        make kustomize
+
+        # replace image
+        $(cd config/manifests && kustomize edit set image "docker.io/apache/camel-k=${{ env.LOCAL_IMAGE }}")
+
+
+        # CSV the patch to force OLM upgrade
+        export RELEASE_VERSION=$(make get-version | grep -Po "\d.\d.\d")
+        cat <<EOF > config/manifests/patch.yml
+        apiVersion: operators.coreos.com/v1alpha1
+        kind: ClusterServiceVersion
+        metadata:
+          namespace: placeholder
+          name: camel-k.v$(make get-last-released-version)
+          annotations:
+            olm.skipRange: ">=1.0.0 <${RELEASE_VERSION}"
+        EOF
+
+        echo "Patching CSV with"
+        cat config/manifests/patch.yml
+        $(cd config/manifests && kustomize edit add patch patch.yml)
+
+        export LOCAL_IMAGE_BUNDLE=$KIND_REGISTRY/apache/camel-k-bundle:$(make get-version)
+        echo "LOCAL_IMAGE_BUNDLE=${LOCAL_IMAGE_BUNDLE}" >> $GITHUB_ENV
+        make bundle-build METADATA_IMAGE_NAME=${LOCAL_IMAGE_BUNDLE} BUNDLE_METADATA_OPTS="--channels stable"
+        docker push ${LOCAL_IMAGE_BUNDLE}
+    - name: Create new index image
+      run: |
+        export LOCAL_IIB=$KIND_REGISTRY/apache/camel-k-iib:$(make get-version)
+        echo "LOCAL_IIB=${LOCAL_IIB}" >> $GITHUB_ENV
+        opm index add --bundles ${{ env.LOCAL_IMAGE_BUNDLE }} --from-index quay.io/operatorhubio/catalog:latest --tag ${LOCAL_IIB} --skip-tls
+        podman push --tls-verify=false ${LOCAL_IIB}
     - name: Run IT
       run: |
         # Use the last released Kamel CLI
-        export KAMEL_BIN=/usr/local/bin/kamel
+        export RELEASED_KAMEL_BIN=/usr/local/bin/kamel
 
         # Configure install options
         export KAMEL_INSTALL_BUILD_PUBLISH_STRATEGY=Spectrum
@@ -105,10 +161,9 @@ jobs:
         export KAMEL_INSTALL_REGISTRY=$KIND_REGISTRY
         export KAMEL_INSTALL_REGISTRY_INSECURE=true
 
-        # TODO: Install OLM and cover upgrade managed by OLM
-        export KAMEL_INSTALL_OLM=false
-
         # Configure test options
+        export CAMEL_K_PREV_IIB=quay.io/operatorhubio/catalog:latest
+        export CAMEL_K_NEW_IIB=${{ env.LOCAL_IIB }}
         export KAMEL_K_TEST_RELEASE_VERSION=$(make get-last-released-version)
         export KAMEL_K_TEST_OPERATOR_CURRENT_IMAGE=$KIND_REGISTRY/apache/camel-k:$(make get-version)
 
diff --git a/config/manifests/kustomization.yaml b/config/manifests/kustomization.yaml
index 8697eb8..3dba3bd 100644
--- a/config/manifests/kustomization.yaml
+++ b/config/manifests/kustomization.yaml
@@ -19,3 +19,4 @@ resources:
 - ../default
 - ../samples
 - ../scorecard
+- ./bases/camel-k.clusterserviceversion.yaml
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 1b45266..6e2632f 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -27,6 +27,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	v1alpha12 "github.com/operator-framework/api/pkg/operators/v1alpha1"
 	"io"
 	"io/ioutil"
 	"os"
@@ -34,6 +35,7 @@ import (
 	"strings"
 	"testing"
 	"time"
+	"unsafe"
 
 	"github.com/google/uuid"
 	"github.com/onsi/gomega"
@@ -116,6 +118,7 @@ func init() {
 	client.FastMapperAllowedAPIGroups["eventing.knative.dev"] = true
 	client.FastMapperAllowedAPIGroups["messaging.knative.dev"] = true
 	client.FastMapperAllowedAPIGroups["serving.knative.dev"] = true
+	client.FastMapperAllowedAPIGroups["operators.coreos.com"] = true
 	client.FastMapperAllowedAPIGroups["policy"] = true
 
 	var err error
@@ -670,6 +673,65 @@ func KnativeService(ns string, name string) func() *servingv1.Service {
 	}
 }
 
+func CKClusterServiceVersion(conditions func(v1alpha12.ClusterServiceVersion) bool ,ns string) func() *v1alpha12.ClusterServiceVersion {
+	return func() *v1alpha12.ClusterServiceVersion {
+		lst := v1alpha12.ClusterServiceVersionList{}
+		if err := TestClient().List(TestContext, &lst, ctrl.InNamespace(ns)); err != nil {
+			panic(err)
+		}
+		for _, s := range lst.Items {
+			if strings.Contains(s.Name, "camel-k") && conditions(s){
+				return &s
+			}
+		}
+		return nil
+	}
+}
+
+func CKClusterServiceVersionPhase(conditions func(v1alpha12.ClusterServiceVersion) bool, ns string) func() v1alpha12.ClusterServiceVersionPhase {
+	return func() v1alpha12.ClusterServiceVersionPhase {
+		if csv := CKClusterServiceVersion(conditions, ns)(); csv != nil && unsafe.Sizeof(csv.Status) > 0 {
+			return csv.Status.Phase
+		}
+		return ""
+	}
+}
+
+func CatalogSource(name string, ns string) func() *v1alpha12.CatalogSource {
+	return func() *v1alpha12.CatalogSource {
+		answer := v1alpha12.CatalogSource{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "CatalogSource",
+				APIVersion: v1alpha1.SchemeGroupVersion.String(),
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Namespace: ns,
+				Name:      name,
+			},
+		}
+		key := ctrl.ObjectKey{
+			Namespace: ns,
+			Name:      name,
+		}
+		if err := TestClient().Get(TestContext, key, &answer); err != nil && k8serrors.IsNotFound(err) {
+			return nil
+		} else if err != nil {
+			log.Errorf(err, "Error while retrieving CatalogSource %s", name)
+			return nil
+		}
+		return &answer
+	}
+}
+
+func CatalogSourcePhase(name string, ns string) func() string {
+	return func() string {
+		if source := CatalogSource(name, ns)(); source != nil && source.Status.GRPCConnectionState != nil {
+			return CatalogSource(name, ns)().Status.GRPCConnectionState.LastObservedState
+		}
+		return ""
+	}
+}
+
 func Deployment(ns string, name string) func() *appsv1.Deployment {
 	return func() *appsv1.Deployment {
 		answer := appsv1.Deployment{
diff --git a/e2e/upgrade/olm_upgrade_test.go b/e2e/upgrade/olm_upgrade_test.go
new file mode 100644
index 0000000..2913493
--- /dev/null
+++ b/e2e/upgrade/olm_upgrade_test.go
@@ -0,0 +1,163 @@
+// +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 (
+	"fmt"
+	. "github.com/apache/camel-k/e2e/support"
+	. "github.com/onsi/gomega"
+	"github.com/operator-framework/api/pkg/lib/version"
+	"github.com/operator-framework/api/pkg/operators/v1alpha1"
+	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"os"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+	"testing"
+)
+
+const CATALOG_SOURCE_NAME = "test-camel-k-source"
+
+func TestOLMAutomaticUpgrade(t *testing.T) {
+	prevIIB := os.Getenv("CAMEL_K_PREV_IIB")
+	newIIB := os.Getenv("CAMEL_K_NEW_IIB")
+	kamel := os.Getenv("RELEASED_KAMEL_BIN")
+
+	if prevIIB == "" || newIIB == "" {
+		t.Skip("OLM Upgrade test needs CAMEL_K_PREV_IIB and CAMEL_K_PREV_IIB ENV variables")
+	}
+
+	WithNewTestNamespace(t, func(ns string) {
+		Expect(createCatalogSource(CATALOG_SOURCE_NAME, prevIIB, ns)).To(Succeed())
+		Eventually(CatalogSourcePhase(CATALOG_SOURCE_NAME, ns), TestTimeoutMedium).Should(Equal("READY"))
+
+		//set KAMEL_BIN only for this test - don't override the ENV variable for all tests
+		Expect(os.Setenv("KAMEL_BIN", kamel)).To(Succeed())
+
+		Expect(Kamel("install", "-n", ns, "--olm=true", "--olm-source", CATALOG_SOURCE_NAME, "--olm-source-namespace", ns).Execute()).To(Succeed())
+
+		//find the only one Camel-K CSV
+		noAdditionalConditions := func(csv v1alpha1.ClusterServiceVersion) bool {
+			return true
+		}
+		Eventually(CKClusterServiceVersionPhase(noAdditionalConditions, ns), TestTimeoutMedium).Should(Equal(v1alpha1.CSVPhaseSucceeded))
+
+		// Refresh the test client to account for the newly installed CRDs
+		SyncClient()
+
+		var prevCSVVersion version.OperatorVersion
+		var newCSVVersion version.OperatorVersion
+
+		// IntegrationPlatform should match at least on the version prefix
+		// CSV patch version can be increased with the OperatorHub respin of the same Camel-K release
+		var prevIPVersionPrefix string
+		var newIPVersionPrefix string
+
+		prevCSVVersion = CKClusterServiceVersion(noAdditionalConditions, ns)().Spec.Version
+		prevIPVersionPrefix = fmt.Sprintf("%d.%d", prevCSVVersion.Version.Major, prevCSVVersion.Version.Minor)
+
+		Expect(OperatorPod(ns)).ToNot(BeNil())
+
+		Expect(Kamel("run", "-n", ns, "files/yaml.yaml").Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "yaml"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+
+		Eventually(PlatformVersion(ns)).Should(ContainSubstring(prevIPVersionPrefix))
+		Expect(IntegrationVersion(ns, "yaml")()).To(ContainSubstring(prevIPVersionPrefix))
+
+		t.Run("OLM upgrade", func(t *testing.T) {
+
+			//invoke OLM upgrade
+			Expect(createCatalogSource(CATALOG_SOURCE_NAME, newIIB, ns)).To(Succeed())
+
+			// previous CSV is REPLACING
+			Eventually(CKClusterServiceVersionPhase(func(csv v1alpha1.ClusterServiceVersion) bool {
+				return csv.Spec.Version.Version.String() == prevCSVVersion.Version.String()
+			}, ns), TestTimeoutMedium).Should(Equal(v1alpha1.CSVPhaseReplacing))
+
+			// the new version is installed
+			Eventually(CKClusterServiceVersionPhase(func(csv v1alpha1.ClusterServiceVersion) bool {
+				return csv.Spec.Version.Version.String() != prevCSVVersion.Version.String()
+			}, ns), TestTimeoutMedium).Should(Equal(v1alpha1.CSVPhaseSucceeded))
+
+			// the old version is gone
+			Eventually(CKClusterServiceVersion(func(csv v1alpha1.ClusterServiceVersion) bool {
+				return csv.Spec.Version.Version.String() == prevCSVVersion.Version.String()
+			}, ns), TestTimeoutMedium).Should(BeNil())
+
+			newCSVVersion = CKClusterServiceVersion(noAdditionalConditions, ns)().Spec.Version
+			newIPVersionPrefix = fmt.Sprintf("%d.%d", newCSVVersion.Version.Major, newCSVVersion.Version.Minor)
+
+			Expect(prevCSVVersion.Version.String()).NotTo(Equal(newCSVVersion.Version.String()))
+
+			Eventually(OperatorPodPhase(ns)).Should(Equal(v1.PodRunning))
+
+			Eventually(PlatformVersion(ns)).Should(ContainSubstring(newIPVersionPrefix))
+		})
+
+		t.Run("Integration upgrade", func(t *testing.T) {
+
+			// Clear the KAMEL_BIN environment variable so that the current version is used from now on
+			Expect(os.Setenv("KAMEL_BIN", "")).To(Succeed())
+
+			Expect(IntegrationVersion(ns, "yaml")()).To(ContainSubstring(prevIPVersionPrefix))
+			Expect(Kamel("rebuild", "yaml", "-n", ns).Execute()).To(Succeed())
+
+			Eventually(IntegrationVersion(ns, "yaml"), TestTimeoutMedium).Should(ContainSubstring(newIPVersionPrefix))
+			Eventually(IntegrationPodPhase(ns, "yaml")).Should(Equal(v1.PodRunning))
+
+			// Clean up
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+			Expect(Kamel("uninstall", "-n", ns).Execute()).To(Succeed())
+		})
+
+	})
+}
+
+func createCatalogSource(name string, image string, ns string) error {
+	catalogSource := v1alpha1.CatalogSource{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "CatalogSource",
+			APIVersion: v1alpha1.SchemeGroupVersion.String(),
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: ns,
+			Name:      name,
+		},
+	}
+	key := ctrl.ObjectKey{
+		Namespace: ns,
+		Name:      name,
+	}
+	if err := TestClient().Get(TestContext, key, &catalogSource); errors.IsNotFound(err) {
+		catalogSource.Spec = v1alpha1.CatalogSourceSpec{
+			Image:       image,
+			SourceType:  "grpc",
+			DisplayName: "OLM upgrade test Catalog",
+			Publisher:   "grpc",
+		}
+		return TestClient().Create(TestContext, &catalogSource)
+	} else {
+		catalogSource.Spec.Image = image
+		return TestClient().Update(TestContext, &catalogSource)
+	}
+
+}
diff --git a/e2e/upgrade/upgrade_operator_test.go b/e2e/upgrade/upgrade_operator_test.go
index 9510846..2ce5775 100644
--- a/e2e/upgrade/upgrade_operator_test.go
+++ b/e2e/upgrade/upgrade_operator_test.go
@@ -36,6 +36,9 @@ import (
 )
 
 func TestOperatorUpgrade(t *testing.T) {
+	// Clean all cluster-wide resources that could corrupt the test run
+	Expect(Kamel("uninstall", "--all", "--olm=false").Execute()).To(Succeed())
+
 	WithNewTestNamespace(t, func(ns string) {
 		version, ok := os.LookupEnv("KAMEL_K_TEST_RELEASE_VERSION")
 		Expect(ok).To(BeTrue())
@@ -43,8 +46,14 @@ func TestOperatorUpgrade(t *testing.T) {
 		image, ok := os.LookupEnv("KAMEL_K_TEST_OPERATOR_CURRENT_IMAGE")
 		Expect(ok).To(BeTrue())
 
-		Expect(Kamel("install", "--cluster-setup").Execute()).To(Succeed())
-		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		kamel, ok := os.LookupEnv("RELEASED_KAMEL_BIN")
+		Expect(ok).To(BeTrue())
+
+		//set KAMEL_BIN only for this test - don't override the ENV variable for all tests
+		Expect(os.Setenv("KAMEL_BIN", kamel)).To(Succeed())
+
+		Expect(Kamel("install", "--olm=false", "--cluster-setup", "--force").Execute()).To(Succeed())
+		Expect(Kamel("install", "--olm=false", "-n", ns).Execute()).To(Succeed())
 
 		// Check the operator pod is running
 		Eventually(OperatorPodPhase(ns), TestTimeoutMedium).Should(Equal(v1.PodRunning))
@@ -69,8 +78,8 @@ func TestOperatorUpgrade(t *testing.T) {
 
 		// Upgrade the operator by installing the current version
 		// FIXME: it seems forcing the installation does not re-install the CRDs
-		Expect(Kamel("install", "--cluster-setup", "--force").Execute()).To(Succeed())
-		Expect(Kamel("install", "-n", ns, "--force", "--operator-image", image).Execute()).To(Succeed())
+		Expect(Kamel("install", "--olm=false", "--cluster-setup", "--force").Execute()).To(Succeed())
+		Expect(Kamel("install", "-n", ns, "--olm=false", "--force", "--operator-image", image).Execute()).To(Succeed())
 
 		// Check the operator image is the current built one
 		Eventually(OperatorImage(ns)).Should(Equal(image))
@@ -99,5 +108,6 @@ func TestOperatorUpgrade(t *testing.T) {
 
 		// Clean up
 		Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+		Expect(Kamel("uninstall", "--all", "--olm=false").Execute()).To(Succeed())
 	})
 }