diff --git a/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json b/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json index d838eda39..b37739db3 100644 --- a/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json +++ b/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json @@ -9,6 +9,36 @@ "lifecycle": "blocking", "environmentSelector": {} }, + { + "name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for singleNamespace watch mode with quay-operator should install a cluster extension successfully", + "labels": {}, + "resources": { + "isolation": {} + }, + "source": "openshift:payload:olmv1", + "lifecycle": "blocking", + "environmentSelector": {} + }, + { + "name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with quay-operator should install a cluster extension successfully", + "labels": {}, + "resources": { + "isolation": {} + }, + "source": "openshift:payload:olmv1", + "lifecycle": "blocking", + "environmentSelector": {} + }, + { + "name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with an operator that does not support ownNamespace installation mode should fail to install a cluster extension successfully", + "labels": {}, + "resources": { + "isolation": {} + }, + "source": "openshift:payload:olmv1", + "lifecycle": "blocking", + "environmentSelector": {} + }, { "name": "[sig-olmv1] OLMv1 should pass a trivial sanity check", "labels": {}, diff --git a/openshift/tests-extension/test/olmv1-singleownnamespace.go b/openshift/tests-extension/test/olmv1-singleownnamespace.go new file mode 100644 index 000000000..0ec83268e --- /dev/null +++ b/openshift/tests-extension/test/olmv1-singleownnamespace.go @@ -0,0 +1,266 @@ +package test + +import ( + "context" + "fmt" + "time" + + //nolint:staticcheck // ST1001: dot-imports for readability + . "github.com/onsi/ginkgo/v2" + //nolint:staticcheck // ST1001: dot-imports for readability + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + "sigs.k8s.io/controller-runtime/pkg/client" + + olmv1 "github.com/operator-framework/operator-controller/api/v1" + + "github/operator-framework-operator-controller/openshift/tests-extension/pkg/env" + "github/operator-framework-operator-controller/openshift/tests-extension/pkg/helpers" +) + +var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for singleNamespace watch mode with quay-operator", Serial, func() { + var ( + k8sClient client.Client + namespace string + testPrefix = "quay-singlens" + ) + + BeforeEach(func() { + By("checking if OpenShift is available for tests") + if !env.Get().IsOpenShift { + Skip("Requires OpenShift for the tests") + } + + k8sClient = env.Get().K8sClient + namespace = fmt.Sprintf("olmv1-%s-ns-%s", testPrefix, rand.String(4)) + + By("ensuring no ClusterExtension and CRD for quay-operator") + helpers.EnsureCleanupClusterExtension(context.Background(), "quay-operator", "quayregistries.quay.redhat.com") + + By(fmt.Sprintf("creating namespace %s for single-namespace tests", namespace)) + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace) + DeferCleanup(func() { + By(fmt.Sprintf("cleaning up namespace %s", namespace)) + _ = k8sClient.Delete(context.Background(), ns) + }) + }) + + It("should install a cluster extension successfully", func(ctx SpecContext) { + unique := rand.String(4) + saName := fmt.Sprintf("install-%s-sa-%s", testPrefix, unique) + crbName := fmt.Sprintf("install-%s-crb-%s", testPrefix, unique) + ceName := fmt.Sprintf("install-%s-ce-%s", testPrefix, unique) + + By("creating ServiceAccount") + sa := helpers.NewServiceAccount(saName, namespace) + Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName) + By("ensuring ServiceAccount is available before proceeding") + helpers.ExpectServiceAccountExists(ctx, saName, namespace) + By("registering cleanup for ServiceAccount") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ServiceAccount %s in namespace %s", sa.Name, sa.Namespace)) + _ = k8sClient.Delete(ctx, sa) + }) + + By("creating ClusterRoleBinding") + crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace) + Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName) + By("ensuring ClusterRoleBinding is available before proceeding") + helpers.ExpectClusterRoleBindingExists(ctx, crbName) + By("registering cleanup for ClusterRoleBinding") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterRoleBinding %s", crb.Name)) + _ = k8sClient.Delete(ctx, crb) + }) + + By("creating ClusterExtension with the watch-namespace annotation") + ce := helpers.NewClusterExtensionObject("quay-operator", "3.14.2", ceName, saName, namespace) + ce.Annotations = map[string]string{ + "olm.operatorframework.io/watch-namespace": namespace, + } + Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName) + By("registering cleanup for ClusterExtension") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterExtension %s", ce.Name)) + _ = k8sClient.Delete(ctx, ce) + }) + + By("waiting for the ClusterExtension to be installed") + helpers.ExpectClusterExtensionToBeInstalled(ctx, ceName) + }) +}) + +var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with quay-operator", Serial, func() { + var ( + k8sClient client.Client + namespace string + testPrefix = "quay-own-ns" + ) + + BeforeEach(func() { + By("checking if OpenShift is available for tests") + if !env.Get().IsOpenShift { + Skip("Requires OpenShift for the tests") + } + + k8sClient = env.Get().K8sClient + namespace = fmt.Sprintf("olmv1-%s-ns-%s", testPrefix, rand.String(4)) + + By("ensuring no ClusterExtension and CRD for quay-operator") + helpers.EnsureCleanupClusterExtension(context.Background(), "quay-operator", "quayregistries.quay.redhat.com") + + By(fmt.Sprintf("creating namespace %s for own-namespace tests", namespace)) + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace) + DeferCleanup(func() { + By(fmt.Sprintf("cleaning up namespace %s", namespace)) + _ = k8sClient.Delete(context.Background(), ns) + }) + }) + + It("should install a cluster extension successfully", func(ctx SpecContext) { + unique := rand.String(4) + saName := fmt.Sprintf("install-%s-sa-%s", testPrefix, unique) + crbName := fmt.Sprintf("install-%s-crb-%s", testPrefix, unique) + ceName := fmt.Sprintf("install-%s-ce-%s", testPrefix, unique) + + By("creating ServiceAccount") + sa := helpers.NewServiceAccount(saName, namespace) + Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName) + By("ensuring ServiceAccount is available before proceeding") + helpers.ExpectServiceAccountExists(ctx, saName, namespace) + By("registering cleanup for ServiceAccount") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ServiceAccount %s in namespace %s", sa.Name, sa.Namespace)) + _ = k8sClient.Delete(ctx, sa) + }) + + By("creating ClusterRoleBinding") + crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace) + Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName) + By("ensuring ClusterRoleBinding is available before proceeding") + helpers.ExpectClusterRoleBindingExists(ctx, crbName) + By("registering cleanup for ClusterRoleBinding") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterRoleBinding %s", crb.Name)) + _ = k8sClient.Delete(ctx, crb) + }) + + By("creating ClusterExtension with the watch-namespace annotation") + ce := helpers.NewClusterExtensionObject("quay-operator", "3.14.2", ceName, saName, namespace) + ce.Annotations = map[string]string{ + "olm.operatorframework.io/watch-namespace": namespace, + } + Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName) + By("registering cleanup for ClusterExtension") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterExtension %s", ce.Name)) + _ = k8sClient.Delete(ctx, ce) + }) + + By("waiting for the ClusterExtension to be installed") + helpers.ExpectClusterExtensionToBeInstalled(ctx, ceName) + }) +}) + +var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with an operator that does not support ownNamespace installation mode", Serial, func() { + var ( + k8sClient client.Client + namespace string + testPrefix = "pipelines-fail-own-ns" + ) + + BeforeEach(func() { + By("checking if OpenShift is available for tests") + if !env.Get().IsOpenShift { + Skip("Requires OpenShift for the tests") + } + + k8sClient = env.Get().K8sClient + namespace = fmt.Sprintf("olmv1-%s-ns-%s", testPrefix, rand.String(4)) + + By("ensuring no ClusterExtension and CRD for openshift-pipelines-operator-rh") + helpers.EnsureCleanupClusterExtension(context.Background(), "openshift-pipelines-operator-rh", "clustertasks.tekton.dev") + + By(fmt.Sprintf("creating namespace %s for failing tests", namespace)) + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace) + DeferCleanup(func() { + By(fmt.Sprintf("cleaning up namespace %s", namespace)) + _ = k8sClient.Delete(context.Background(), ns) + }) + }) + + It("should fail to install a cluster extension successfully", func(ctx SpecContext) { + unique := rand.String(4) + saName := fmt.Sprintf("install-%s-sa-%s", testPrefix, unique) + crbName := fmt.Sprintf("install-%s-crb-%s", testPrefix, unique) + ceName := fmt.Sprintf("install-%s-ce-%s", testPrefix, unique) + + By("creating ServiceAccount") + sa := helpers.NewServiceAccount(saName, namespace) + Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName) + By("ensuring ServiceAccount is available before proceeding") + helpers.ExpectServiceAccountExists(ctx, saName, namespace) + By("registering cleanup for ServiceAccount") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ServiceAccount %s in namespace %s", sa.Name, sa.Namespace)) + _ = k8sClient.Delete(ctx, sa) + }) + + By("creating ClusterRoleBinding") + crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace) + Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName) + By("ensuring ClusterRoleBinding is available before proceeding") + helpers.ExpectClusterRoleBindingExists(ctx, crbName) + By("registering cleanup for ClusterRoleBinding") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterRoleBinding %s", crb.Name)) + _ = k8sClient.Delete(ctx, crb) + }) + + By("creating ClusterExtension with the watch-namespace annotation") + ce := helpers.NewClusterExtensionObject("openshift-pipelines-operator-rh", "1.17.1", ceName, saName, namespace) + ce.Annotations = map[string]string{ + "olm.operatorframework.io/watch-namespace": namespace, + } + Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName) + By("registering cleanup for ClusterExtension") + DeferCleanup(func() { + By(fmt.Sprintf("cleanup: deleting ClusterExtension %s", ce.Name)) + _ = k8sClient.Delete(ctx, ce) + }) + + By("waiting for the ClusterExtension to fail installation") + Eventually(func(g Gomega) { + var ext olmv1.ClusterExtension + err := k8sClient.Get(ctx, client.ObjectKey{Name: ceName}, &ext) + g.Expect(err).ToNot(HaveOccurred(), "failed to get ClusterExtension %q", ceName) + + conditions := ext.Status.Conditions + g.Expect(conditions).ToNot(BeEmpty(), "ClusterExtension %q has empty status.conditions", ceName) + + installed := meta.FindStatusCondition(conditions, olmv1.TypeInstalled) + g.Expect(installed).ToNot(BeNil(), "Installed condition not found") + g.Expect(installed.Status).To(Equal(metav1.ConditionFalse), "Installed should be False") + g.Expect(installed.Reason).To(Equal("Failed")) + }).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed()) + }) +})