Skip to content

Add OLM Install & Delete Testing #917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ kuttl-test.json

!vendor/**/zz_generated.*

# editor and IDE paraphernalia
# editor and IDE paraphernalia (inc MacOs)
.idea
*.swp
*.swo
*~
.DS_Store


# ignore vendor
vendor/
Expand Down
71 changes: 28 additions & 43 deletions test/openshift/e2e/ginkgo/fixture/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd"
deploymentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/deployment"
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s"
osFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/os"
osFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/os" // Corrected import path
subscriptionFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/subscription"
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
appsv1 "k8s.io/api/apps/v1"
Expand All @@ -40,16 +40,18 @@ import (
)

const (
// E2ETestLabelsKey and E2ETestLabelsValue are added to cluster-scoped resources (e.g. Namespaces) created by E2E tests (where possible). On startup (and before each test for sequential tests), any resources with this label will be deleted.
E2ETestLabelsKey = "app"
E2ETestLabelsValue = "test-argo-app"
E2ETestLabelsKey = "app"
E2ETestLabelsValue = "test-argo-app"
GitOpsOperatorNamespace = "openshift-gitops-operator"
GitOpsOperatorDeploymentName = "openshift-gitops-operator-controller-manager"
GitOpsOperatorSubscriptionName = "openshift-gitops-operator"
HelloWorldPattern = "helloworld-operator"
)

var NamespaceLabels = map[string]string{E2ETestLabelsKey: E2ETestLabelsValue}

func EnsureParallelCleanSlate() {

// Increase the maximum length of debug output, for when tests fail
format.MaxLength = 64 * 1024
SetDefaultEventuallyTimeout(time.Second * 60)
SetDefaultEventuallyPollingInterval(time.Second * 3)
Expand All @@ -71,20 +73,12 @@ func EnsureParallelCleanSlate() {
// Unlike sequential clean slate, parallel clean slate cannot assume that there are no other tests running. This limits our ability to clean up old test artifacts.
}

// EnsureSequentialCleanSlate will clean up resources that were created during previous sequential tests
// - Deletes namespaces that were created by previous tests
// - Deletes other cluster-scoped resources that were created
// - Reverts changes made to Subscription CR
// - etc
func EnsureSequentialCleanSlate() {
Expect(EnsureSequentialCleanSlateWithError()).To(Succeed())
}

func EnsureSequentialCleanSlateWithError() error {

// With sequential tests, we are always safe to assume that there is no other test running. That allows us to clean up old test artifacts before new test starts.

// Increase the maximum length of debug output, for when tests fail
format.MaxLength = 64 * 1024
SetDefaultEventuallyTimeout(time.Second * 60)
SetDefaultEventuallyPollingInterval(time.Second * 3)
Expand Down Expand Up @@ -131,8 +125,8 @@ func EnsureSequentialCleanSlateWithError() error {
Enabled: true,
TLS: nil,
// TLS: &routev1.TLSConfig{
// Termination: routev1.TLSTerminationReencrypt,
// InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect,
// Termination: routev1.TLSTerminationReencrypt,
// InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect,
// },
}

Expand Down Expand Up @@ -206,13 +200,12 @@ func EnsureSequentialCleanSlateWithError() error {
func RemoveDynamicPluginFromCSV(ctx context.Context, k8sClient client.Client) error {

if EnvNonOLM() || EnvLocalRun() {
// Skipping as CSV does exist when not using OLM, nor does it exist when running locally
return nil
}

var csv *olmv1alpha1.ClusterServiceVersion
var csvList olmv1alpha1.ClusterServiceVersionList
Expect(k8sClient.List(ctx, &csvList, client.InNamespace("openshift-gitops-operator"))).To(Succeed())
Expect(k8sClient.List(ctx, &csvList, client.InNamespace(GitOpsOperatorNamespace))).To(Succeed())

for idx := range csvList.Items {
idxCSV := csvList.Items[idx]
Expand All @@ -221,7 +214,7 @@ func RemoveDynamicPluginFromCSV(ctx context.Context, k8sClient client.Client) er
break
}
}
Expect(csv).ToNot(BeNil(), "if you see this, it likely means, either: A) the operator is not installed via OLM (and you meant to install it), OR B) you are running the operator locally via 'make run', and thus should specify LOCAL_RUN=true env var when calling the test")
Expect(csv).ToNot(BeNil(), "if you see this, it likely means, either: A) the operator is not installed via OLM (and you meant to install it), OR B) you are running the operator locally via 'make run', and thus should not specify LOCAL_RUN=true env var when calling the test")

if err := updateWithoutConflict(csv, func(obj client.Object) {

Expand Down Expand Up @@ -374,7 +367,7 @@ func GetEnvInOperatorSubscriptionOrDeployment(key string) (*string, error) {
}

if EnvNonOLM() {
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator-controller-manager", Namespace: "openshift-gitops-operator"}}
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorDeploymentName, Namespace: GitOpsOperatorNamespace}}

return deploymentFixture.GetEnv(depl, key)

Expand All @@ -394,7 +387,7 @@ func GetEnvInOperatorSubscriptionOrDeployment(key string) (*string, error) {

} else {

sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator", Namespace: "openshift-gitops-operator"}}
sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorSubscriptionName, Namespace: GitOpsOperatorNamespace}}
if err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(sub), sub); err != nil {
return nil, err
}
Expand All @@ -411,11 +404,11 @@ func SetEnvInOperatorSubscriptionOrDeployment(key string, value string) {
k8sClient, _ := utils.GetE2ETestKubeClient()

if EnvNonOLM() {
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator-controller-manager", Namespace: "openshift-gitops-operator"}}
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorDeploymentName, Namespace: GitOpsOperatorNamespace}}

deploymentFixture.SetEnv(depl, key, value)

WaitForAllDeploymentsInTheNamespaceToBeReady("openshift-gitops-operator", k8sClient)
WaitForAllDeploymentsInTheNamespaceToBeReady(GitOpsOperatorNamespace, k8sClient)

} else if EnvCI() {

Expand All @@ -429,7 +422,7 @@ func SetEnvInOperatorSubscriptionOrDeployment(key string, value string) {

} else {

sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator", Namespace: "openshift-gitops-operator"}}
sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorSubscriptionName, Namespace: GitOpsOperatorNamespace}}
Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(sub), sub)).To(Succeed())

subscriptionFixture.SetEnv(sub, key, value)
Expand All @@ -448,11 +441,11 @@ func RemoveEnvFromOperatorSubscriptionOrDeployment(key string) error {
}

if EnvNonOLM() {
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator-controller-manager", Namespace: "openshift-gitops-operator"}}
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorDeploymentName, Namespace: GitOpsOperatorNamespace}}

deploymentFixture.RemoveEnv(depl, key)

WaitForAllDeploymentsInTheNamespaceToBeReady("openshift-gitops-operator", k8sClient)
WaitForAllDeploymentsInTheNamespaceToBeReady(GitOpsOperatorNamespace, k8sClient)

} else if EnvCI() {

Expand All @@ -470,7 +463,7 @@ func RemoveEnvFromOperatorSubscriptionOrDeployment(key string) error {

} else {

sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator", Namespace: "openshift-gitops-operator"}}
sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorSubscriptionName, Namespace: GitOpsOperatorNamespace}}
if err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(sub), sub); err != nil {
return err
}
Expand All @@ -485,9 +478,7 @@ func RemoveEnvFromOperatorSubscriptionOrDeployment(key string) error {

func GetSubscriptionInEnvCIEnvironment(k8sClient client.Client) (*olmv1alpha1.Subscription, error) {
subscriptionList := olmv1alpha1.SubscriptionList{}
if err := k8sClient.List(context.Background(), &subscriptionList, client.InNamespace("openshift-gitops-operator")); err != nil {
return nil, err
}
Expect(k8sClient.List(context.Background(), &subscriptionList, client.InNamespace(GitOpsOperatorNamespace))).To(Succeed())

var sub *olmv1alpha1.Subscription

Expand Down Expand Up @@ -516,7 +507,7 @@ func RestoreSubcriptionToDefault() error {

if EnvNonOLM() {

depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator-controller-manager", Namespace: "openshift-gitops-operator"}}
depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorDeploymentName, Namespace: GitOpsOperatorNamespace}}

for _, envKey := range optionalEnvVarsToRemove {
deploymentFixture.RemoveEnv(depl, envKey)
Expand All @@ -539,30 +530,26 @@ func RestoreSubcriptionToDefault() error {
subscriptionFixture.RemoveSpecConfig(sub)
}

if err := waitForAllEnvVarsToBeRemovedFromDeployments("openshift-gitops-operator", optionalEnvVarsToRemove, k8sClient); err != nil {
if err := waitForAllEnvVarsToBeRemovedFromDeployments(GitOpsOperatorNamespace, optionalEnvVarsToRemove, k8sClient); err != nil {
return err
}

WaitForAllDeploymentsInTheNamespaceToBeReady("openshift-gitops-operator", k8sClient)

} else if EnvLocalRun() {
// When running locally, there are no cluster resources to clean up
return nil
WaitForAllDeploymentsInTheNamespaceToBeReady(GitOpsOperatorNamespace, k8sClient)

} else {

sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: "openshift-gitops-operator", Namespace: "openshift-gitops-operator"}}
sub := &olmv1alpha1.Subscription{ObjectMeta: metav1.ObjectMeta{Name: GitOpsOperatorSubscriptionName, Namespace: GitOpsOperatorNamespace}}
if err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(sub), sub); err != nil {
return err
}

subscriptionFixture.RemoveSpecConfig(sub)

if err := waitForAllEnvVarsToBeRemovedFromDeployments("openshift-gitops-operator", optionalEnvVarsToRemove, k8sClient); err != nil {
if err := waitForAllEnvVarsToBeRemovedFromDeployments(GitOpsOperatorNamespace, optionalEnvVarsToRemove, k8sClient); err != nil {
return err
}

WaitForAllDeploymentsInTheNamespaceToBeReady("openshift-gitops-operator", k8sClient)
WaitForAllDeploymentsInTheNamespaceToBeReady(GitOpsOperatorNamespace, k8sClient)
}

return nil
Expand Down Expand Up @@ -848,15 +835,14 @@ func OutputDebugOnFail(namespaceParams ...any) {
debugOutput, exists := testReportMap[testName]

if exists && debugOutput.isOutputted {
// Skip output if we have already outputted once for this test
return
}

testReportMap[testName] = testReportEntry{
isOutputted: true,
}

outputPodLog("openshift-gitops-operator-controller-manager")
outputPodLog(GitOpsOperatorDeploymentName)

for _, namespace := range namespaces {

Expand Down Expand Up @@ -911,7 +897,6 @@ func outputPodLog(podSubstring string) {
}

if len(matchingPods) == 0 {
// This can happen when the operator is not running on the cluster
GinkgoWriter.Println("DebugOutputOperatorLogs was called, but no pods were found.")
return
}
Expand All @@ -922,7 +907,7 @@ func outputPodLog(podSubstring string) {
}

// Extract operator logs
kubectlLogOutput, err := osFixture.ExecCommandWithOutputParam(false, "kubectl", "logs", "pod/"+matchingPods[0].Name, "manager", "-n", matchingPods[0].Namespace)
kubectlLogOutput, err := osFixture.ExecCommandWithOutputParam(false, "kubectl", "logs", "pod/"+matchingPods[0].Name, "manager", "-n", GitOpsOperatorNamespace)
if err != nil {
GinkgoWriter.Println("unable to extract operator logs", err)
return
Expand Down
65 changes: 65 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/olm/fixture.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package olm

import (
"context"
"fmt"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

olmv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
apierr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
)

// WaitForClusterServiceVersion waits for a specific ClusterServiceVersion to reach the 'Succeeded' phase.
func WaitForClusterServiceVersion(ctx context.Context, namespace, csvName string, timeout, pollingInterval time.Duration) {
k8sClient, _, err := utils.GetE2ETestKubeClientWithError() // Get client here
Expect(err).ToNot(HaveOccurred())

GinkgoWriter.Printf("Waiting for ClusterServiceVersion '%s' in namespace '%s' to be Succeeded...\n", csvName, namespace)

csvKey := types.NamespacedName{
Name: csvName,
Namespace: namespace,
}

var foundCSV olmv1alpha1.ClusterServiceVersion

Eventually(func() bool {
getErr := k8sClient.Get(ctx, csvKey, &foundCSV)
if getErr != nil {
if apierr.IsNotFound(getErr) {
GinkgoWriter.Printf("CSV '%s' not found yet. Listing all CSVs in '%s' for debug...\n", csvName, namespace)
var csvList olmv1alpha1.ClusterServiceVersionList
listErr := k8sClient.List(ctx, &csvList, client.InNamespace(namespace))
if listErr != nil {
GinkgoWriter.Printf("Error listing CSVs for debug: %v\n", listErr)
} else {
for _, csv := range csvList.Items {
GinkgoWriter.Printf("- Found CSV: %s (Phase: %s, Reason: %s)\n", csv.Name, csv.Status.Phase, csv.Status.Reason)
}
}
return false
}
GinkgoWriter.Printf("Error getting CSV '%s': %v. Retrying...\n", csvName, getErr)
return false // retrying on errors
}

// Check if the CSV phase is Succeeded
if foundCSV.Status.Phase == olmv1alpha1.CSVPhaseSucceeded {
GinkgoWriter.Printf("ClusterServiceVersion '%s' is Succeeded.\n", csvName)
return true
}

GinkgoWriter.Printf("CSV '%s' status is '%s' (Reason: %s). Waiting...\n", csvName, foundCSV.Status.Phase, foundCSV.Status.Reason)
return false // Not succeeded yet
}).WithTimeout(timeout).WithPolling(pollingInterval).Should(BeTrue(),
fmt.Sprintf("Expected ClusterServiceVersion '%s' in namespace '%s' to be Succeeded within %s", csvName, namespace, timeout))

GinkgoWriter.Println("ClusterServiceVersion successfully installed and Succeeded.")
}
Loading
Loading