Skip to content

Commit e585c73

Browse files
committed
Add e2e ginkgo tests for extraCommandargs and Application Health Status
Signed-off-by: Rizwana777 <[email protected]>
1 parent 2f4984c commit e585c73

File tree

2 files changed

+376
-26
lines changed

2 files changed

+376
-26
lines changed

test/openshift/e2e/ginkgo/parallel/1-115_validate_controller_extra_command_args_test.go

Lines changed: 219 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ package parallel
1818

1919
import (
2020
"context"
21+
"fmt"
2122

2223
argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
24+
argoprojv1a1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
2325
. "github.com/onsi/ginkgo/v2"
2426
. "github.com/onsi/gomega"
2527
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture"
@@ -28,7 +30,9 @@ import (
2830
statefulsetFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/statefulset"
2931
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
3032
appsv1 "k8s.io/api/apps/v1"
33+
corev1 "k8s.io/api/core/v1"
3134
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35+
"k8s.io/apimachinery/pkg/types"
3236
"sigs.k8s.io/controller-runtime/pkg/client"
3337
)
3438

@@ -49,8 +53,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
4953

5054
})
5155

52-
It("ensuring that extra arguments can be added to application controller", func() {
53-
56+
It("ensuring extra arguments are deduplicated, replaced, or preserved as expected in application-controller", func() {
5457
By("creating a simple ArgoCD CR and waiting for it to become available")
5558
ns, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
5659
defer cleanupFunc()
@@ -62,61 +65,251 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
6265
},
6366
}
6467
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
65-
6668
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
6769

68-
By("verifying app controller becomes availables")
6970
appControllerSS := &appsv1.StatefulSet{
7071
ObjectMeta: metav1.ObjectMeta{
7172
Name: "example-argocd-application-controller",
7273
Namespace: ns.Name,
7374
},
7475
}
75-
7676
Eventually(appControllerSS).Should(k8sFixture.ExistByName())
7777
Eventually(appControllerSS).Should(statefulsetFixture.HaveReadyReplicas(1))
7878

79-
By("adding a new parameter via .spec.controller.extraCommandArgs")
79+
// 1: Add new flag
80+
By("adding a new flag via extraCommandArgs")
8081
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
81-
ac.Spec.Controller.ExtraCommandArgs = []string{"--app-hard-resync"}
82+
ac.Spec.Controller.ExtraCommandArgs = []string{"--app-hard-resync", "2"}
8283
})
83-
84-
By("verifying new parameter is added, and the existing paramaters are still present")
8584
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--app-hard-resync", 0))
8685

87-
Expect(len(appControllerSS.Spec.Template.Spec.Containers[0].Command)).To(BeNumerically(">=", 10))
86+
// 2: Replace existing non-repeatable flag
87+
By("replacing existing default flag with extraCommandArgs")
88+
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
89+
ac.Spec.Controller.ExtraCommandArgs = []string{
90+
"--status-processors", "15",
91+
"--kubectl-parallelism-limit", "20",
92+
}
93+
})
94+
95+
// Expect new values to appear
96+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--status-processors", 0))
97+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("15", 0))
98+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit", 0))
99+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("20", 0))
88100

89-
By("removing the extra command arg")
101+
// Expect default values to be replaced (old default 10 should not appear)
102+
Consistently(func() bool {
103+
cmd := appControllerSS.Spec.Template.Spec.Containers[0].Command
104+
for i := range cmd {
105+
if cmd[i] == "--status-processors" && i+1 < len(cmd) && cmd[i+1] == "10" {
106+
return true
107+
}
108+
}
109+
return false
110+
}).Should(BeFalse())
111+
112+
// 3: Add duplicate flag+value pairs, which should be ignored
113+
By("adding duplicate flags with same values")
90114
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
91-
ac.Spec.Controller.ExtraCommandArgs = nil
115+
ac.Spec.Controller.ExtraCommandArgs = []string{
116+
"--status-processors", "15", // duplicate
117+
"--kubectl-parallelism-limit", "20", // duplicate
118+
"--hydrator-enabled",
119+
}
92120
})
121+
// Verify --hydrator-enabled gets added
122+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--hydrator-enabled", 0))
123+
124+
// But no duplicate --status-processors or --kubectl-parallelism-limit
125+
Consistently(func() bool {
126+
cmd := appControllerSS.Spec.Template.Spec.Containers[0].Command
93127

94-
By("verifying the parameter has been removed")
95-
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--app-hard-resync", 0))
96-
Consistently(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--app-hard-resync", 0))
97-
Expect(len(appControllerSS.Spec.Template.Spec.Containers[0].Command)).To(BeNumerically(">=", 10))
128+
statusProcessorsCount := 0
129+
kubectlLimitCount := 0
130+
131+
for i := 0; i < len(cmd); i++ {
132+
if cmd[i] == "--status-processors" {
133+
statusProcessorsCount++
134+
}
135+
if cmd[i] == "--kubectl-parallelism-limit" {
136+
kubectlLimitCount++
137+
}
138+
}
98139

99-
By("adding a new extra command arg that has the same name as existing parameters")
140+
// Fail if either flag appears more than once
141+
return statusProcessorsCount > 1 || kubectlLimitCount > 1
142+
}).Should(BeFalse())
143+
144+
// 4: Add a repeatable flag multiple times with different values
145+
By("adding a repeatable flag with multiple values")
100146
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
101147
ac.Spec.Controller.ExtraCommandArgs = []string{
102-
"--status-processors",
103-
"15",
104-
"--kubectl-parallelism-limit",
105-
"20",
148+
"--metrics-application-labels", "application.argoproj.io/template-version",
149+
"--metrics-application-labels", "application.argoproj.io/chart-version",
106150
}
107151
})
108152

109-
// TODO: These lines are currently failing: they are ported correctly from the original kuttl test, but the original kuttl test did not check them correctly (and thus either the behaviour in the operator changed, or the tests never worked)
153+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--metrics-application-labels", 0))
110154

111-
// Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--status-processors 15", 0))
155+
// Check that both --metrics-application-labels flags are present
156+
Eventually(func() bool {
157+
cmd := appControllerSS.Spec.Template.Spec.Containers[0].Command
112158

113-
// Consistently(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--status-processors 15", 0))
159+
metricVals := []string{}
160+
for i := 0; i < len(cmd); i++ {
161+
if cmd[i] == "--metrics-application-labels" && i+1 < len(cmd) {
162+
metricVals = append(metricVals, cmd[i+1])
163+
}
164+
}
114165

115-
// Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit 20", 0))
166+
// Ensure both values are present
167+
hasMetricLabelTemplate := false
168+
hasMetricLabelChart := false
169+
for _, v := range metricVals {
170+
if v == "application.argoproj.io/template-version" {
171+
hasMetricLabelTemplate = true
172+
}
173+
if v == "application.argoproj.io/chart-version" {
174+
hasMetricLabelChart = true
175+
}
176+
}
177+
return hasMetricLabelTemplate && hasMetricLabelChart
178+
}).Should(BeTrue())
116179

117-
// Consistently(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit 20", 0))
180+
// 5: Remove all extra args
181+
By("removing all extra args")
182+
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
183+
ac.Spec.Controller.ExtraCommandArgs = nil
184+
})
118185

186+
// Expect all custom flags to disappear
187+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--metrics-application-labels", 0))
188+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--status-processors 15", 0))
189+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit 20", 0))
190+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--hydrator-enabled", 0))
119191
})
192+
})
193+
194+
})
195+
196+
var _ = Describe("ArgoCD Resource Health Persist", func() {
197+
var (
198+
argoCDName = "example-argocd"
199+
appName = "guestbook"
200+
appNamespace = "guestbook"
201+
)
202+
203+
var (
204+
k8sClient client.Client
205+
ctx context.Context
206+
)
207+
208+
BeforeEach(func() {
209+
fmt.Println("YUOOo")
210+
fixture.EnsureParallelCleanSlate()
211+
212+
k8sClient, _ = fixtureUtils.GetE2ETestKubeClient()
213+
ctx = context.Background()
214+
215+
})
216+
217+
Context("1-115_validate_resource_health_persisted_in_application_status", func() {
218+
It("should persist resource health in Application CR status when configured", func() {
219+
ns, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
220+
defer cleanupFunc()
221+
222+
err := k8sClient.Get(ctx, client.ObjectKey{
223+
Name: ns.Name,
224+
Namespace: ns.Namespace,
225+
}, ns)
226+
Expect(err).Should(BeNil())
120227

228+
By("Creating ArgoCD CR with controller.resource.health.persist=true")
229+
argoCD := &argov1beta1api.ArgoCD{
230+
ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns.Name},
231+
Spec: argov1beta1api.ArgoCDSpec{
232+
Controller: argov1beta1api.ArgoCDApplicationControllerSpec{},
233+
},
234+
}
235+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
236+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
237+
238+
By("Waiting for Application Controller to be ready")
239+
Eventually(func() bool {
240+
deploy := &appsv1.StatefulSet{}
241+
err := k8sClient.Get(ctx, client.ObjectKey{
242+
Name: argoCDName + "-application-controller",
243+
Namespace: ns.Name,
244+
}, deploy)
245+
return err == nil && deploy.Status.ReadyReplicas > 0
246+
}, "1m", "5s").Should(BeTrue())
247+
248+
targetNamespace := &corev1.Namespace{
249+
ObjectMeta: metav1.ObjectMeta{
250+
Name: appNamespace,
251+
Labels: map[string]string{
252+
"argocd.argoproj.io/managed-by": ns.Name,
253+
},
254+
},
255+
}
256+
By("Creating target namespace for Application")
257+
Expect(k8sClient.Create(ctx, targetNamespace)).To(Succeed())
258+
259+
By("Creating ArgoCD Application CR")
260+
app := &argoprojv1a1.Application{
261+
ObjectMeta: metav1.ObjectMeta{
262+
Name: appName,
263+
Namespace: ns.Name,
264+
},
265+
Spec: argoprojv1a1.ApplicationSpec{
266+
Project: "default",
267+
Source: &argoprojv1a1.ApplicationSource{
268+
RepoURL: "https://github.com/Rizwana777/argocd-example-apps",
269+
Path: "guestbook",
270+
TargetRevision: "HEAD",
271+
},
272+
Destination: argoprojv1a1.ApplicationDestination{
273+
Server: "https://kubernetes.default.svc",
274+
Namespace: targetNamespace.Name,
275+
},
276+
SyncPolicy: &argoprojv1a1.SyncPolicy{
277+
Automated: &argoprojv1a1.SyncPolicyAutomated{},
278+
},
279+
},
280+
}
281+
Expect(k8sClient.Create(ctx, app)).To(Succeed())
282+
283+
By("Validating that resource health is persisted in Application CR")
284+
Eventually(func() bool {
285+
var fetched argoprojv1a1.Application
286+
err := k8sClient.Get(ctx, types.NamespacedName{
287+
Name: appName,
288+
Namespace: ns.Name,
289+
}, &fetched)
290+
if err != nil {
291+
return false
292+
}
293+
294+
// Check if application has resources with health information
295+
if len(fetched.Status.Resources) == 0 {
296+
return false
297+
}
298+
299+
for _, res := range fetched.Status.Resources {
300+
if res.Health == nil {
301+
return false
302+
}
303+
if res.Health.Status == "" {
304+
return false
305+
}
306+
}
307+
308+
// Validate resourceHealthSource is NOT present (it is omitted when health is persisted)
309+
return len(fetched.Status.ResourceHealthSource) == 0
310+
}, "3m", "5s").Should(BeTrue())
311+
312+
Expect(k8sClient.Delete(ctx, targetNamespace)).To(Succeed())
313+
})
121314
})
122315
})

0 commit comments

Comments
 (0)