Skip to content

Commit e7f915c

Browse files
committed
feat(tests): Add tests for gitops-must-gather
Signed-off-by: Oliver Gondža <[email protected]>
1 parent e339d22 commit e7f915c

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package parallel
18+
19+
import (
20+
"context"
21+
"fmt"
22+
osFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/os"
23+
"os"
24+
"path"
25+
"strings"
26+
27+
argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
28+
. "github.com/onsi/ginkgo/v2"
29+
. "github.com/onsi/gomega"
30+
"github.com/onsi/gomega/types"
31+
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
32+
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture"
33+
argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd"
34+
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
35+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
36+
"sigs.k8s.io/yaml"
37+
38+
"sigs.k8s.io/controller-runtime/pkg/client"
39+
)
40+
41+
// MustGatherImage is a good place to insert development image
42+
// Known to be buggy in 1.17.0
43+
const MustGatherImage = "registry.redhat.io/openshift-gitops-1/must-gather-rhel8:v1.16.0" // TODO, use tag name with SUT version
44+
45+
var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
46+
47+
Context("1-120_validate_running_must_gather", func() {
48+
49+
var (
50+
k8sClient client.Client
51+
ctx context.Context
52+
)
53+
54+
BeforeEach(func() {
55+
fixture.EnsureParallelCleanSlate()
56+
k8sClient, _ = fixtureUtils.GetE2ETestKubeClient()
57+
ctx = context.Background()
58+
})
59+
60+
It("verified the files collected for must gather are valid", func() {
61+
62+
By("creating namespace-scoped Argo CD instance")
63+
ns, nsCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
64+
defer nsCleanup()
65+
66+
nsf, nsfCleanup := fixture.CreateManagedNamespaceWithCleanupFunc(ns.Name+"-follower", ns.Name)
67+
defer nsfCleanup()
68+
69+
argoCD := &argov1beta1api.ArgoCD{
70+
ObjectMeta: metav1.ObjectMeta{Name: "left-argocd", Namespace: ns.Name},
71+
Spec: argov1beta1api.ArgoCDSpec{},
72+
}
73+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
74+
75+
By("waiting for ArgoCD CRs to be reconciled and the instances to be ready in " + ns.Name)
76+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
77+
78+
// TODO https://github.com/redhat-developer/gitops-must-gather/blob/135850b74b56b6fda9fc68ed4165a88b5c7dbeaf/gather_gitops.sh#L40
79+
// TODO https://github.com/redhat-developer/gitops-must-gather/blob/135850b74b56b6fda9fc68ed4165a88b5c7dbeaf/gather_gitops.sh#L61
80+
// TODO https://github.com/redhat-developer/gitops-must-gather/blob/135850b74b56b6fda9fc68ed4165a88b5c7dbeaf/gather_gitops.sh#L79
81+
82+
destDir := gather()
83+
defer os.RemoveAll(destDir)
84+
85+
Expect(path.Join(destDir, "must-gather.logs")).To(BeARegularFile())
86+
Expect(path.Join(destDir, "event-filter.html")).To(BeARegularFile())
87+
Expect(path.Join(destDir, "timestamp")).To(BeARegularFile())
88+
89+
resources := resourcesDir(destDir)
90+
Expect(path.Join(resources, "gather.logs")).To(BeARegularFile())
91+
csr := path.Join(resources, "cluster-scoped-resources")
92+
Expect(csr).To(BeADirectory())
93+
Expect(path.Join(csr, "apiextensions.k8s.io/customresourcedefinitions/applications.argoproj.io.yaml")).To(BeValidResourceFile())
94+
Expect(path.Join(csr, "argoproj.io/clusteranalysistemplates.yaml")).To(BeValidResourceFile())
95+
Expect(path.Join(csr, "config.openshift.io/clusterversions/version.yaml")).To(BeValidResourceFile())
96+
97+
n := path.Join(resources, "namespaces")
98+
Expect(n).To(BeADirectory())
99+
Expect(path.Join(n, "openshift-gitops/openshift-gitops.yaml")).To(BeValidResourceFile())
100+
Expect(path.Join(n, "openshift-gitops/route.openshift.io/routes.yaml")).To(BeValidResourceFile())
101+
Expect(path.Join(n, "openshift-gitops/argoproj.io/appprojects.yaml")).To(BeValidResourceFile())
102+
logs := path.Join(n, "openshift-gitops/pods/openshift-gitops-application-controller-0/argocd-application-controller/argocd-application-controller/logs/")
103+
Expect(path.Join(logs, "current.log")).To(BeARegularFile())
104+
Expect(path.Join(logs, "previous.log")).To(BeARegularFile())
105+
106+
Expect(path.Join(n, nsf.Name, "core/pods.yaml")).To(BeValidResourceFile())
107+
})
108+
})
109+
})
110+
111+
func gather() string {
112+
destDir, err := os.MkdirTemp("", "gitops-operator-e2e-must-gather-test-1-120_*")
113+
Expect(err).ToNot(HaveOccurred())
114+
115+
stdout, err := osFixture.ExecCommandWithOutputParam(
116+
true,
117+
"oc", "adm", "must-gather", "--image", MustGatherImage, "--dest-dir", destDir,
118+
)
119+
Expect(err).ToNot(HaveOccurred())
120+
121+
errorLines := make([]string, 0)
122+
for _, line := range strings.Split(stdout, "\n") {
123+
if strings.Contains(line, "error:") {
124+
errorLines = append(errorLines, line)
125+
}
126+
}
127+
Expect(errorLines).To(BeEmpty(), "Errors found in must gather output")
128+
return destDir
129+
}
130+
131+
func resourcesDir(destDir string) string {
132+
// Find the only subdirectory which contains must-gather data
133+
entries, err := os.ReadDir(destDir)
134+
Expect(err).ToNot(HaveOccurred())
135+
136+
var subdirs []string
137+
for _, entry := range entries {
138+
if entry.IsDir() {
139+
subdirs = append(subdirs, entry.Name())
140+
}
141+
}
142+
143+
Expect(len(subdirs)).To(Equal(1), "Expected exactly one subdirectory, found: %v", subdirs)
144+
return path.Join(destDir, subdirs[0])
145+
}
146+
147+
func isCSVInstalled(ctx context.Context, k8sClient client.Client, subscription *operatorsv1alpha1.Subscription) bool {
148+
key := client.ObjectKey{
149+
Name: subscription.Name,
150+
Namespace: subscription.Namespace,
151+
}
152+
153+
if err := k8sClient.Get(ctx, key, subscription); err != nil {
154+
return false
155+
}
156+
157+
return subscription.Status.InstalledCSV != ""
158+
}
159+
160+
// BeValidResourceFile checks if the file exists and if it is a valid YAML file.
161+
func BeValidResourceFile() types.GomegaMatcher {
162+
return &validResourceFile{}
163+
}
164+
165+
type validResourceFile struct{}
166+
167+
func (matcher *validResourceFile) Match(actual any) (success bool, err error) {
168+
filePath, ok := actual.(string)
169+
if !ok {
170+
return false, fmt.Errorf("BeValidResourceFile matcher expects a string (file path)")
171+
}
172+
173+
content, err := os.ReadFile(filePath)
174+
if err != nil {
175+
return false, fmt.Errorf("failed to read file: %v", err)
176+
}
177+
println(string(content))
178+
179+
var data map[string]any
180+
if err := yaml.Unmarshal(content, &data); err != nil {
181+
return false, fmt.Errorf("failed parsing supposed YAML file: %v", err)
182+
}
183+
184+
_, exists := data["kind"]
185+
return exists, nil
186+
}
187+
188+
func (matcher *validResourceFile) FailureMessage(actual any) string {
189+
return fmt.Sprintf("Expected\n\t%v\nto be a valid YAML resource file", actual)
190+
}
191+
192+
func (matcher *validResourceFile) NegatedFailureMessage(actual any) string {
193+
return fmt.Sprintf("Expected\n\t%v\nnot to be a valid YAML resource file", actual)
194+
}

0 commit comments

Comments
 (0)