Skip to content

Commit f1696c0

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

File tree

1 file changed

+217
-26
lines changed

1 file changed

+217
-26
lines changed

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

Lines changed: 217 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121

2222
argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
23+
argoprojv1a1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
2324
. "github.com/onsi/ginkgo/v2"
2425
. "github.com/onsi/gomega"
2526
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture"
@@ -28,7 +29,9 @@ import (
2829
statefulsetFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/statefulset"
2930
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
3031
appsv1 "k8s.io/api/apps/v1"
32+
corev1 "k8s.io/api/core/v1"
3133
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/apimachinery/pkg/types"
3235
"sigs.k8s.io/controller-runtime/pkg/client"
3336
)
3437

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

5053
})
5154

52-
It("ensuring that extra arguments can be added to application controller", func() {
53-
55+
It("ensuring extra arguments are deduplicated, replaced, or preserved as expected in application-controller", func() {
5456
By("creating a simple ArgoCD CR and waiting for it to become available")
5557
ns, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
5658
defer cleanupFunc()
@@ -62,61 +64,250 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
6264
},
6365
}
6466
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
65-
6667
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
6768

68-
By("verifying app controller becomes availables")
6969
appControllerSS := &appsv1.StatefulSet{
7070
ObjectMeta: metav1.ObjectMeta{
7171
Name: "example-argocd-application-controller",
7272
Namespace: ns.Name,
7373
},
7474
}
75-
7675
Eventually(appControllerSS).Should(k8sFixture.ExistByName())
7776
Eventually(appControllerSS).Should(statefulsetFixture.HaveReadyReplicas(1))
7877

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

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

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

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))
127+
statusProcessorsCount := 0
128+
kubectlLimitCount := 0
129+
130+
for i := 0; i < len(cmd); i++ {
131+
if cmd[i] == "--status-processors" {
132+
statusProcessorsCount++
133+
}
134+
if cmd[i] == "--kubectl-parallelism-limit" {
135+
kubectlLimitCount++
136+
}
137+
}
98138

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

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)
152+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--metrics-application-labels", 0))
110153

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

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

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

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

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

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

0 commit comments

Comments
 (0)