This is an automated email from the ASF dual-hosted git repository. pcongiusti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit e6f63825b43ea63a6a9c4a88b57bfc43c28ce6b8 Author: Pasquale Congiusti <[email protected]> AuthorDate: Tue Aug 6 14:59:01 2024 +0200 chore(ci): simplify OLM testing --- .github/workflows/install.yml | 9 ++- e2e/install/helm/setup_test.go | 6 +- e2e/install/olm/olm_install_test.go | 90 ++++++++++----------------- e2e/install/upgrade/upgrade_test.go | 2 +- e2e/support/csv.go | 120 ------------------------------------ e2e/support/test_util.go | 11 +++- script/Makefile | 9 ++- script/build_bundle_index.sh | 18 +++--- 8 files changed, 70 insertions(+), 195 deletions(-) diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index cfa8cff8b..088ecb69e 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -90,12 +90,15 @@ jobs: kubectl create -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.28.0/olm.yaml kubectl wait --for=jsonpath='{.status.phase}'=Succeeded csv packageserver -n olm --timeout=2m - - name: Build OLM bundle + - name: Build and push OLM bundle shell: bash run: | - make bundle-build + echo "BUNDLE_IMAGE_NAME=docker.io/squakez/camel-k-bundle" >> $GITHUB_ENV + echo "Setting bundle image name as as $BUNDLE_IMAGE_NAME which is required by OLM tests" + # TODO publish in a staging environment accordingly + # BUNDLE_IMAGE_NAME=docker.io/squakez/camel-k-bundle make bundle-push - - name: Run test + - name: Run tests shell: bash run: | DO_TEST_PREBUILD=false GOTESTFMT="-json 2>&1 | gotestfmt" make test-install diff --git a/e2e/install/helm/setup_test.go b/e2e/install/helm/setup_test.go index b6d5d2645..e6f632754 100644 --- a/e2e/install/helm/setup_test.go +++ b/e2e/install/helm/setup_test.go @@ -38,14 +38,14 @@ import ( ) func TestHelmInstallation(t *testing.T) { - KAMEL_INSTALL_REGISTRY := os.Getenv("KAMEL_INSTALL_REGISTRY") + containerRegistry, ok := os.LookupEnv("KAMEL_INSTALL_REGISTRY") + g.Expect(ok).To(BeTrue()) WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) { // Let's make sure no CRD is yet available in the cluster // as we must make the Helm procedure to install them accordingly g.Eventually(CRDs(t)).Should(BeNil()) operatorID := "helm-ck" - g.Expect(KAMEL_INSTALL_REGISTRY).NotTo(Equal("")) os.Setenv("CAMEL_K_TEST_MAKE_DIR", "../../../") ExpectExecSucceed(t, g, exec.Command( @@ -54,7 +54,7 @@ func TestHelmInstallation(t *testing.T) { "camel-k", fmt.Sprintf("../../../docs/charts/camel-k-%s.tgz", defaults.Version), "--set", - fmt.Sprintf("platform.build.registry.address=%s", KAMEL_INSTALL_REGISTRY), + fmt.Sprintf("platform.build.registry.address=%s", containerRegistry), "--set", "platform.build.registry.insecure=true", "--set", diff --git a/e2e/install/olm/olm_install_test.go b/e2e/install/olm/olm_install_test.go index 4c92fdb05..bf4834e51 100644 --- a/e2e/install/olm/olm_install_test.go +++ b/e2e/install/olm/olm_install_test.go @@ -26,91 +26,55 @@ import ( "context" "fmt" "os" - "os/exec" - "strings" "testing" . "github.com/apache/camel-k/v2/e2e/support" . "github.com/onsi/gomega" - "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" olm "github.com/operator-framework/api/pkg/operators/v1alpha1" + v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/util/defaults" "github.com/apache/camel-k/v2/pkg/util/kubernetes" - "github.com/apache/camel-k/v2/pkg/util/openshift" ) const installCatalogSourceName = "test-camel-k-source" func TestOLMInstallation(t *testing.T) { WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) { + bundleImageName, ok := os.LookupEnv("BUNDLE_IMAGE_NAME") + g.Expect(ok).To(BeTrue()) + containerRegistry, ok := os.LookupEnv("KAMEL_INSTALL_REGISTRY") + g.Expect(ok).To(BeTrue()) os.Setenv("CAMEL_K_TEST_MAKE_DIR", "../../../") - // Set the configuration required for OLM to work with local catalog - // Build Camel K local bundle - ExpectExecSucceed(t, g, - Make(t, "bundle-build"), - ) - // Build Operator local index - ExpectExecSucceed(t, g, - Make(t, "bundle-index"), - ) - - // This workaround is required because of - // https://github.com/operator-framework/operator-lifecycle-manager/issues/903#issuecomment-1779366630 - cmd := exec.Command("docker", "inspect", "--format={{.Id}}", "apache/camel-k-bundle-index:2.4.0-SNAPSHOT") - out, err := cmd.Output() - require.NoError(t, err) - newBundleIndexSha := strings.ReplaceAll(string(out), "\n", "") - g.Expect(newBundleIndexSha).To(Not(Equal(""))) - - newBundleIndex := fmt.Sprintf("apache/camel-k-bundle-index@%s", newBundleIndexSha) - g.Expect(CreateOrUpdateCatalogSource(t, ctx, ns, installCatalogSourceName, newBundleIndex)).To(Succeed()) - - ocp, err := openshift.IsOpenShift(TestClient(t)) - require.NoError(t, err) - - if ocp { - // Wait for pull secret to be created in namespace - // eg. test-camel-k-source-dockercfg-zlltn - secretPrefix := fmt.Sprintf("%s-dockercfg-", installCatalogSourceName) - g.Eventually(SecretByName(t, ctx, ns, secretPrefix), TestTimeoutLong).Should(Not(BeNil())) - } - - g.Eventually(CatalogSourcePodRunning(t, ctx, ns, installCatalogSourceName), TestTimeoutMedium).Should(BeNil()) - g.Eventually(CatalogSourcePhase(t, ctx, ns, installCatalogSourceName), TestTimeoutLong).Should(Equal("READY")) - - // Install via OLM subscription (should use the latest default available channel) - ExpectExecSucceed(t, g, - exec.Command( - "kubectl", - "apply", - "-f", - "https://operatorhub.io/install/camel-k/camel-k.yaml", + // Install staged bundle (it must be available by building it before running the test) + // You can build it locally via `make bundle-push` action + ExpectExecSucceedWithTimeout(t, g, + Make(t, + "bundle-test", + fmt.Sprintf("BUNDLE_IMAGE_NAME=%s", bundleImageName), + fmt.Sprintf("NAMESPACE=%s", ns), ), + "180s", ) - // Find the only one Camel K CSV noAdditionalConditions := func(csv olm.ClusterServiceVersion) bool { return true } - g.Eventually(ClusterServiceVersionPhase(t, ctx, noAdditionalConditions, ns), TestTimeoutMedium).Should(Equal(olm.CSVPhaseSucceeded)) - - // Refresh the test client to account for the newly installed CRDs - RefreshClient(t) - - csvVersion := ClusterServiceVersion(t, ctx, noAdditionalConditions, ns)().Spec.Version - ipVersionPrefix := fmt.Sprintf("%d.%d", csvVersion.Version.Major, csvVersion.Version.Minor) - t.Logf("CSV Version installed: %s", csvVersion.Version.String()) - + g.Eventually(ClusterServiceVersionPhase(t, ctx, noAdditionalConditions, ns), TestTimeoutMedium). + Should(Equal(olm.CSVPhaseSucceeded)) // Check the operator pod is running g.Eventually(OperatorPodPhase(t, ctx, ns), TestTimeoutMedium).Should(Equal(corev1.PodRunning)) g.Eventually(OperatorImage(t, ctx, ns), TestTimeoutShort).Should(Equal(defaults.OperatorImage())) - // Check the IntegrationPlatform has been reconciled - g.Eventually(PlatformVersion(t, ctx, ns)).Should(ContainSubstring(ipVersionPrefix)) + // Check the IntegrationPlatform has been reconciled after setting the expected container registry + g.Expect(UpdatePlatform(t, ctx, ns, func(ip *v1.IntegrationPlatform) { + ip.Spec.Build.Registry.Address = containerRegistry + })).To(Succeed()) + g.Eventually(PlatformPhase(t, ctx, ns), TestTimeoutMedium).Should(Equal(v1.IntegrationPlatformPhaseReady)) + g.Eventually(PlatformVersion(t, ctx, ns), TestTimeoutMedium).Should(Equal(defaults.Version)) // Check if restricted security context has been applyed operatorPod := OperatorPod(t, ctx, ns)() @@ -118,5 +82,17 @@ func TestOLMInstallation(t *testing.T) { g.Expect(operatorPod.Spec.Containers[0].SecurityContext.Capabilities).To(Equal(kubernetes.DefaultOperatorSecurityContext().Capabilities)) g.Expect(operatorPod.Spec.Containers[0].SecurityContext.SeccompProfile).To(Equal(kubernetes.DefaultOperatorSecurityContext().SeccompProfile)) g.Expect(operatorPod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(Equal(kubernetes.DefaultOperatorSecurityContext().AllowPrivilegeEscalation)) + + // Test a simple integration is running + g.Expect(KamelRun(t, ctx, ns, "files/yaml.yaml").Execute()).To(Succeed()) + g.Eventually(IntegrationPodPhase(t, ctx, ns, "yaml"), TestTimeoutMedium).Should(Equal(corev1.PodRunning)) + g.Eventually(IntegrationConditionStatus(t, ctx, ns, "yaml", v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue)) + g.Eventually(IntegrationLogs(t, ctx, ns, "yaml"), TestTimeoutShort).Should(ContainSubstring("Magicstring!")) + + // TODO Remove OLM CSV and test + // g.Eventually(OperatorPod(t, ctx, ns)).Should(BeNil()) + // g.Eventually(Platform(t, ctx, ns)).Should(BeNil()) + // g.Eventually(Integration(t, ctx, ns, "yaml"), TestTimeoutShort).ShouldNot(BeNil()) + // g.Eventually(IntegrationConditionStatus(t, ctx, ns, "yaml", v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue)) }) } diff --git a/e2e/install/upgrade/upgrade_test.go b/e2e/install/upgrade/upgrade_test.go index 236b53a20..b699a2579 100644 --- a/e2e/install/upgrade/upgrade_test.go +++ b/e2e/install/upgrade/upgrade_test.go @@ -39,7 +39,7 @@ import ( "github.com/apache/camel-k/v2/pkg/util/defaults" ) -func TestKustomizeUpgrade(t *testing.T) { +func TestUpgrade(t *testing.T) { WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) { // We start the test by installing previous version operator lastVersion, ok := os.LookupEnv("LAST_RELEASED_VERSION") diff --git a/e2e/support/csv.go b/e2e/support/csv.go index c4bb04eae..9a4da70f3 100644 --- a/e2e/support/csv.go +++ b/e2e/support/csv.go @@ -24,22 +24,13 @@ package support import ( "context" - "fmt" "strings" "testing" - "time" "unsafe" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" - ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" olm "github.com/operator-framework/api/pkg/operators/v1alpha1" - - "github.com/apache/camel-k/v2/pkg/util/log" ) func ClusterServiceVersion(t *testing.T, ctx context.Context, conditions func(olm.ClusterServiceVersion) bool, ns string) func() *olm.ClusterServiceVersion { @@ -65,114 +56,3 @@ func ClusterServiceVersionPhase(t *testing.T, ctx context.Context, conditions fu return "" } } - -func CreateOrUpdateCatalogSource(t *testing.T, ctx context.Context, ns, name, image string) error { - catalogSource := &olm.CatalogSource{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, - }, - } - - _, err := ctrlutil.CreateOrUpdate(ctx, TestClient(t), catalogSource, func() error { - catalogSource.Spec = olm.CatalogSourceSpec{ - Image: image, - SourceType: "grpc", - DisplayName: "OLM upgrade test Catalog", - Publisher: "grpc", - } - return nil - }) - - return err -} - -func CatalogSource(t *testing.T, ctx context.Context, ns, name string) func() *olm.CatalogSource { - return func() *olm.CatalogSource { - cs := &olm.CatalogSource{ - TypeMeta: metav1.TypeMeta{ - Kind: "CatalogSource", - APIVersion: olm.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, - }, - } - if err := TestClient(t).Get(ctx, ctrl.ObjectKeyFromObject(cs), cs); err != nil && k8serrors.IsNotFound(err) { - return nil - } else if err != nil { - log.Errorf(err, "Error while retrieving CatalogSource %s", name) - return nil - } - return cs - } -} - -func CatalogSourcePhase(t *testing.T, ctx context.Context, ns, name string) func() string { - return func() string { - if source := CatalogSource(t, ctx, ns, name)(); source != nil && source.Status.GRPCConnectionState != nil { - return CatalogSource(t, ctx, ns, name)().Status.GRPCConnectionState.LastObservedState - } - return "" - } -} - -func CatalogSourcePod(t *testing.T, ctx context.Context, ns, csName string) func() *corev1.Pod { - return func() *corev1.Pod { - podList, err := TestClient(t).CoreV1().Pods(ns).List(ctx, metav1.ListOptions{}) - if err != nil && k8serrors.IsNotFound(err) { - return nil - } else if err != nil { - panic(err) - } - - if len(podList.Items) == 0 { - return nil - } - - for _, pod := range podList.Items { - if strings.HasPrefix(pod.Name, csName) { - return &pod - } - } - - return nil - } -} - -func CatalogSourcePodRunning(t *testing.T, ctx context.Context, ns, csName string) error { - podFunc := CatalogSourcePod(t, ctx, ns, csName) - - for i := 1; i < 5; i++ { - csPod := podFunc() - if csPod != nil && csPod.Status.Phase == "Running" { - return nil // Pod good to go - } - - if i == 2 { - fmt.Println("Catalog Source Pod still not ready so delete & allow it to be redeployed ...") - if err := TestClient(t).Delete(ctx, csPod); err != nil { - return err - } - } - - fmt.Println("Catalog Source Pod not ready so waiting for 2 minutes ...") - time.Sleep(2 * time.Minute) - } - - return fmt.Errorf("Catalog Source Pod failed to reach a 'running' state") -} - -func GetSubscription(t *testing.T, ctx context.Context, ns string) (*olm.Subscription, error) { - lst := olm.SubscriptionList{} - if err := TestClient(t).List(ctx, &lst, ctrl.InNamespace(ns)); err != nil { - return nil, err - } - for _, s := range lst.Items { - if strings.Contains(s.Name, "camel-k") { - return &s, nil - } - } - return nil, nil -} diff --git a/e2e/support/test_util.go b/e2e/support/test_util.go index 5bbeb2153..c95f5d1fd 100644 --- a/e2e/support/test_util.go +++ b/e2e/support/test_util.go @@ -132,6 +132,10 @@ func UninstallCRDs(t *testing.T, ctx context.Context, g *WithT, makedir string) } func ExpectExecSucceed(t *testing.T, g *WithT, command *exec.Cmd) { + ExpectExecSucceedWithTimeout(t, g, command, "") +} + +func ExpectExecSucceedWithTimeout(t *testing.T, g *WithT, command *exec.Cmd, timeout string) { t.Helper() var cmdOut strings.Builder @@ -146,7 +150,12 @@ func ExpectExecSucceed(t *testing.T, g *WithT, command *exec.Cmd) { RegisterTestingT(t) session, err := gexec.Start(command, &cmdOut, &cmdErr) - session.Wait() + if timeout != "" { + session.Wait(timeout) + } else { + session.Wait() + } + g.Eventually(session).Should(gexec.Exit(0)) require.NoError(t, err) assert.NotContains(t, strings.ToUpper(cmdErr.String()), "ERROR") diff --git a/script/Makefile b/script/Makefile index 06656ad2c..846228650 100644 --- a/script/Makefile +++ b/script/Makefile @@ -30,7 +30,7 @@ LAST_RELEASED_VERSION ?= 2.4.0 DEFAULT_RUNTIME_VERSION := 3.8.1 CONTROLLER_GEN_VERSION := v0.15.0 CODEGEN_VERSION := v0.29.7 -OPERATOR_SDK_VERSION := v1.28.0 +OPERATOR_SDK_VERSION := v1.30.0 KUSTOMIZE_VERSION := v4.5.4 OPM_VERSION := v1.24.0 LINTER_VERSION ?= v1.59.1 @@ -690,6 +690,13 @@ bundle-build: bundle bundle-push: bundle-build docker push $(BUNDLE_IMAGE_NAME):$(CUSTOM_VERSION) +bundle-test: operator-sdk +ifndef NAMESPACE + @echo "WARN: no namespace specified, using default namespace $(DEFAULT_NS)" + $(eval NAMESPACE=$(DEFAULT_NS)) +endif + $(OPERATOR_SDK) run bundle $(BUNDLE_IMAGE_NAME):$(CUSTOM_VERSION) -n $(NAMESPACE) + # # Builds a test catalog index for installing the operator via an OLM # diff --git a/script/build_bundle_index.sh b/script/build_bundle_index.sh index 976ee0cc2..8471d2126 100755 --- a/script/build_bundle_index.sh +++ b/script/build_bundle_index.sh @@ -156,15 +156,15 @@ do fi done -# echo -n "Validating index ... " -# STATUS=$(${OPM} validate ${INDEX_DIR} 2>&1) -# if [ $? != 0 ]; then -# echo "Failed" -# echo "Error: ${STATUS}" -# exit 1 -# else -# echo "OK" -# fi +echo -n "Validating index ... " +STATUS=$(${OPM} validate ${INDEX_DIR} 2>&1) +if [ $? != 0 ]; then + echo "Failed" + echo "Error: ${STATUS}" + exit 1 +else + echo "OK" +fi echo -n "Generating catalog dockerfile ... " STATUS=$(${OPM} generate dockerfile ${INDEX_DIR} 2>&1)
