Skip to content
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/argoproj/gitops-engine v0.7.1-0.20250617174952-093aef0dad58
github.com/go-logr/logr v1.4.3
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.1-0.20241114170450-2d3c2a9cc518
github.com/hashicorp/go-version v1.7.0
github.com/onsi/ginkgo/v2 v2.22.2
github.com/onsi/gomega v1.36.2
Expand Down Expand Up @@ -87,7 +88,6 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.1-0.20241114170450-2d3c2a9cc518 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down
39 changes: 39 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/argocd/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,45 @@ func HaveApplicationControllerOperationProcessors(operationProcessors int) match
})
}

func HaveCondition(condition metav1.Condition) matcher.GomegaMatcher {
return fetchArgoCD(func(argocd *argov1beta1api.ArgoCD) bool {

if len(argocd.Status.Conditions) != 1 {
GinkgoWriter.Println("HaveCondition: length is zero")
return false
}

instanceCondition := argocd.Status.Conditions[0]

GinkgoWriter.Println("HaveCondition - Message:", instanceCondition.Message, condition.Message)
if instanceCondition.Message != condition.Message {
GinkgoWriter.Println("HaveCondition: message does not match")
return false
}

GinkgoWriter.Println("HaveCondition - Reason:", instanceCondition.Reason, condition.Reason)
if instanceCondition.Reason != condition.Reason {
GinkgoWriter.Println("HaveCondition: reason does not match")
return false
}

GinkgoWriter.Println("HaveCondition - Status:", instanceCondition.Status, condition.Status)
if instanceCondition.Status != condition.Status {
GinkgoWriter.Println("HaveCondition: status does not match")
return false
}

GinkgoWriter.Println("HaveCondition - Type:", instanceCondition.Type, condition.Type)
if instanceCondition.Type != condition.Type {
GinkgoWriter.Println("HaveCondition: type does not match")
return false
}

return true

})
}

// This is intentionally NOT exported, for now. Create another function in this file/package that calls this function, and export that.
func fetchArgoCD(f func(*argov1beta1api.ArgoCD) bool) matcher.GomegaMatcher {

Expand Down
13 changes: 11 additions & 2 deletions test/openshift/e2e/ginkgo/fixture/configmap/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,16 @@ func HaveStringDataKeyValue(key string, value string) matcher.GomegaMatcher {
GinkgoWriter.Println("HaveStringDataKeyValue: ConfigMag key", key, "Have:", a, "Expected:", value)
}

return string(a) == value
return a == value
})

}

// NotHaveStringDataKey returns true if ConfigMap's .data 'key' does not exist, false otherwise
func NotHaveStringDataKey(key string) matcher.GomegaMatcher {
return fetchConfigMap(func(cm *corev1.ConfigMap) bool {
_, exists := cm.Data[key]
return !exists
})

}
Expand Down Expand Up @@ -108,7 +117,7 @@ func HaveStringDataKeyValueContainsSubstring(key string, substring string) match
GinkgoWriter.Println("HaveStringDataKeyValue: ConfigMag key", key, "Value:", a, "Expected:", substring)
}

return strings.Contains(string(a), substring)
return strings.Contains(a, substring)
})

}
Expand Down
33 changes: 33 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/deployment/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ func GetTemplateSpecContainerByName(name string, depl appsv1.Deployment) *corev1
return nil
}

func HaveTemplateSpec(podTemplateSpec corev1.PodTemplateSpec) matcher.GomegaMatcher {
return fetchDeployment(func(depl *appsv1.Deployment) bool {

templateSpec := depl.Spec.Template.Spec

if templateSpec.NodeSelector == nil {
GinkgoWriter.Println("HaveTemplateSpec - .spec.template.spec is nil")
return false
}

GinkgoWriter.Println("HaveTemplateSpec - expected:", podTemplateSpec, "actual:", templateSpec)
return reflect.DeepEqual(podTemplateSpec, templateSpec)
})

}

func HaveTemplateSpecNodeSelector(nodeSelector map[string]string) matcher.GomegaMatcher {
return fetchDeployment(func(depl *appsv1.Deployment) bool {

Expand Down Expand Up @@ -337,6 +353,23 @@ func HaveContainerWithEnvVar(envKey string, envValue string, containerIndex int)
})
}

func HaveSpecTemplateSpecVolume(volumeParam corev1.Volume) matcher.GomegaMatcher {
return fetchDeployment(func(depl *appsv1.Deployment) bool {

GinkgoWriter.Println("HaveSpecTemplateSpecVolume - Volumes:")
for _, volume := range depl.Spec.Template.Spec.Volumes {
GinkgoWriter.Println("-", volume)

if reflect.DeepEqual(volumeParam, volume) {
return true
}
}

return false
})

}

func HaveConditionTypeStatus(expectedConditionType appsv1.DeploymentConditionType, expectedConditionStatus corev1.ConditionStatus) matcher.GomegaMatcher {
return fetchDeployment(func(depl *appsv1.Deployment) bool {

Expand Down
80 changes: 64 additions & 16 deletions test/openshift/e2e/ginkgo/fixture/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -254,7 +255,7 @@ func CreateRandomE2ETestNamespace() *corev1.Namespace {

testNamespaceName := "gitops-e2e-test-" + randomVal

ns := CreateNamespace(string(testNamespaceName))
ns := CreateNamespace(testNamespaceName)
return ns
}

Expand Down Expand Up @@ -329,23 +330,26 @@ func CreateManagedNamespaceWithCleanupFunc(name string, managedByNamespace strin
func nsDeletionFunc(ns *corev1.Namespace) func() {

return func() {
DeleteNamespace(ns)
}

// If you are debugging an E2E test and want to prevent its namespace from being deleted when the test ends (so that you can examine the state of resources in the namespace) you can set E2E_DEBUG_SKIP_CLEANUP env var.
if os.Getenv("E2E_DEBUG_SKIP_CLEANUP") != "" {
GinkgoWriter.Println("Skipping namespace cleanup as E2E_DEBUG_SKIP_CLEANUP is set")
return
}

k8sClient, _, err := utils.GetE2ETestKubeClientWithError()
Expect(err).ToNot(HaveOccurred())
err = k8sClient.Delete(context.Background(), ns, &client.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationForeground)})
}

// Error shouldn't occur, UNLESS it's because the NS no longer exists
if err != nil && !apierr.IsNotFound(err) {
Expect(err).ToNot(HaveOccurred())
}
func DeleteNamespace(ns *corev1.Namespace) {
// If you are debugging an E2E test and want to prevent its namespace from being deleted when the test ends (so that you can examine the state of resources in the namespace) you can set E2E_DEBUG_SKIP_CLEANUP env var.
if os.Getenv("E2E_DEBUG_SKIP_CLEANUP") != "" {
GinkgoWriter.Println("Skipping namespace cleanup as E2E_DEBUG_SKIP_CLEANUP is set")
return
}

k8sClient, _, err := utils.GetE2ETestKubeClientWithError()
Expect(err).ToNot(HaveOccurred())
err = k8sClient.Delete(context.Background(), ns, &client.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationForeground)})

// Error shouldn't occur, UNLESS it's because the NS no longer exists
if err != nil && !apierr.IsNotFound(err) {
Expect(err).ToNot(HaveOccurred())
}
}

// EnvNonOLM checks if NON_OLM var is set; this variable is set when testing on GitOps operator that is not installed via OLM
Expand Down Expand Up @@ -804,7 +808,8 @@ var testReportMap = map[string]testReportEntry{} // acquire testReportLock befor
// - Namespace parameter may be a string, *Namespace, or Namespace
func OutputDebugOnFail(namespaceParams ...any) {

// Convert parameter to string of namespace name
// Convert parameter to string of namespace name:
// - You can specify Namespace, *Namespae, or string, and we will convert it to string namespace
namespaces := []string{}
for _, param := range namespaceParams {

Expand Down Expand Up @@ -852,7 +857,7 @@ func OutputDebugOnFail(namespaceParams ...any) {

kubectlOutput, err := osFixture.ExecCommandWithOutputParam(false, "kubectl", "get", "all", "-n", namespace)
if err != nil {
GinkgoWriter.Println("unable to extract operator logs for namespace", namespace, err, kubectlOutput)
GinkgoWriter.Println("unable to list", namespace, err, kubectlOutput)
continue
}

Expand All @@ -862,6 +867,18 @@ func OutputDebugOnFail(namespaceParams ...any) {
GinkgoWriter.Println(kubectlOutput)
GinkgoWriter.Println("----------------------------------------------------------------")

kubectlOutput, err = osFixture.ExecCommandWithOutputParam(false, "kubectl", "get", "deployments", "-n", namespace, "-o", "yaml")
if err != nil {
GinkgoWriter.Println("unable to list", namespace, err, kubectlOutput)
continue
}

GinkgoWriter.Println("")
GinkgoWriter.Println("----------------------------------------------------------------")
GinkgoWriter.Println("'kubectl get deployments -n " + namespace + " -o yaml")
GinkgoWriter.Println(kubectlOutput)
GinkgoWriter.Println("----------------------------------------------------------------")

}

kubectlOutput, err := osFixture.ExecCommandWithOutputParam(false, "kubectl", "get", "argocds", "-A", "-o", "yaml")
Expand All @@ -877,6 +894,37 @@ func OutputDebugOnFail(namespaceParams ...any) {

}

// EnsureRunningOnOpenShift should be called if a test requires OpenShift (for example, it uses Route CR).
func EnsureRunningOnOpenShift() {

runningOnOpenShift := RunningOnOpenShift()

if !runningOnOpenShift {
Skip("This test requires the cluster to be OpenShift")
return
}

Expect(runningOnOpenShift).To(BeTrueBecause("this test is marked as requiring an OpenShift cluster, and we have detected the cluster is OpenShift"))

}

// RunningOnOpenShift returns true if the cluster is an OpenShift cluster, false otherwise.
func RunningOnOpenShift() bool {
k8sClient, _ := utils.GetE2ETestKubeClient()

crdList := crdv1.CustomResourceDefinitionList{}
Expect(k8sClient.List(context.Background(), &crdList)).To(Succeed())

openshiftAPIsFound := 0
for _, crd := range crdList.Items {
if strings.Contains(crd.Spec.Group, "openshift.io") {
openshiftAPIsFound++
}
}
return openshiftAPIsFound > 5 // I picked 5 as an arbitrary number, could also just be 1
}

//nolint:unused
func outputPodLog(podSubstring string) {
k8sClient, _, err := utils.GetE2ETestKubeClientWithError()
if err != nil {
Expand Down
6 changes: 4 additions & 2 deletions test/openshift/e2e/ginkgo/fixture/rolebinding/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import (

func HaveSubject(subjectParam rbacv1.Subject) matcher.GomegaMatcher {
return fetchRoleBinding(func(r *rbacv1.RoleBinding) bool {
for _, subject := range r.Subjects {

GinkgoWriter.Println("HaveSubject - ", subject, subjectParam)
GinkgoWriter.Println("HaveSubject - Want:", subjectParam)
for idx, subject := range r.Subjects {

GinkgoWriter.Printf("%d) HaveSubject - Have: %s\n", idx+1, subject)
if reflect.DeepEqual(subjectParam, subject) {
return true
}
Expand Down
16 changes: 16 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/secret/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ func UpdateWithError(obj *corev1.Secret, modify func(*corev1.Secret)) error {
return err
}

// HaveNonEmptyKeyValue returns true if Secret has the given key, and the value of the key is non-empty
func HaveNonEmptyKeyValue(key string) matcher.GomegaMatcher {
return fetchSecret(func(sec *corev1.Secret) bool {
a, exists := sec.Data[key]
if !exists {
GinkgoWriter.Println("HaveNonEmptyKeyValue - Key:", key, "does not exist")
return false
}

GinkgoWriter.Println("HaveNonEmptyKeyValue - Key:", key, " Have:", string(a))

return len(a) > 0
})

}

// HaveStringDataKeyValue returns true if Secret has 'key' field under .data map, and the value of that field is equal to 'value'
func HaveStringDataKeyValue(key string, value string) matcher.GomegaMatcher {
return fetchSecret(func(sec *corev1.Secret) bool {
Expand Down
5 changes: 5 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/utils/fixtureUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
admissionv1 "k8s.io/api/admissionregistration/v1"
apps "k8s.io/api/apps/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
Expand Down Expand Up @@ -132,6 +133,10 @@ func getKubeClient(config *rest.Config) (client.Client, *runtime.Scheme, error)
return nil, nil, err
}

if err := batchv1.AddToScheme(scheme); err != nil {
return nil, nil, err
}

k8sClient, err := client.New(config, client.Options{Scheme: scheme})
if err != nil {
return nil, nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
deploymentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/deployment"
k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s"
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
corev1 "k8s.io/api/apps/v1"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -106,7 +106,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
Expect(argoCDAlpha1.Spec.SSO.Dex.OpenShiftOAuth).To(BeTrue())
Expect(argoCDAlpha1.Spec.Server.Route.Enabled).To(BeTrue())

dexDeployment := &corev1.Deployment{
dexDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "argocd-dex-server",
Namespace: ns.Name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
ctx = context.Background()
})

It("ensures that certificates can be confirmed on server and webhook Routes", func() {
It("ensures that certificates can be confirmed on server and webhook Routes", func() {

fixture.EnsureRunningOnOpenShift()

ns, nsCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
defer nsCleanup()
Expand Down
Loading