Skip to content

Commit ef5ab29

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

File tree

2 files changed

+252
-27
lines changed

2 files changed

+252
-27
lines changed

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

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
4949

5050
})
5151

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

68-
By("verifying app controller becomes availables")
6966
appControllerSS := &appsv1.StatefulSet{
7067
ObjectMeta: metav1.ObjectMeta{
7168
Name: "example-argocd-application-controller",
7269
Namespace: ns.Name,
7370
},
7471
}
75-
7672
Eventually(appControllerSS).Should(k8sFixture.ExistByName())
7773
Eventually(appControllerSS).Should(statefulsetFixture.HaveReadyReplicas(1))
7874

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

87-
Expect(len(appControllerSS.Spec.Template.Spec.Containers[0].Command)).To(BeNumerically(">=", 10))
82+
// 2: Replace existing non-repeatable flag
83+
By("replacing existing default flag with extraCommandArgs")
84+
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
85+
ac.Spec.Controller.ExtraCommandArgs = []string{
86+
"--status-processors", "15",
87+
"--kubectl-parallelism-limit", "20",
88+
}
89+
})
8890

89-
By("removing the extra command arg")
91+
// Expect new values to appear
92+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--status-processors", 0))
93+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("15", 0))
94+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit", 0))
95+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("20", 0))
96+
97+
// Expect default values to be replaced (old default 10 should not appear)
98+
Consistently(func() bool {
99+
cmd := appControllerSS.Spec.Template.Spec.Containers[0].Command
100+
for i := range cmd {
101+
if cmd[i] == "--status-processors" && i+1 < len(cmd) && cmd[i+1] == "10" {
102+
return true
103+
}
104+
}
105+
return false
106+
}).Should(BeFalse())
107+
108+
// 3: Add duplicate flag+value pairs, which should be ignored
109+
By("adding duplicate flags with same values")
90110
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
91-
ac.Spec.Controller.ExtraCommandArgs = nil
111+
ac.Spec.Controller.ExtraCommandArgs = []string{
112+
"--status-processors", "15", // duplicate
113+
"--kubectl-parallelism-limit", "20", // duplicate
114+
"--hydrator-enabled",
115+
}
92116
})
117+
// Verify --hydrator-enabled gets added
118+
Eventually(appControllerSS).Should(statefulsetFixture.HaveContainerCommandSubstring("--hydrator-enabled", 0))
119+
120+
// But no duplicate --status-processors or --kubectl-parallelism-limit
121+
Consistently(func() bool {
122+
cmd := appControllerSS.Spec.Template.Spec.Containers[0].Command
123+
124+
statusProcessorsCount := 0
125+
kubectlLimitCount := 0
126+
127+
for i := 0; i < len(cmd); i++ {
128+
if cmd[i] == "--status-processors" {
129+
statusProcessorsCount++
130+
}
131+
if cmd[i] == "--kubectl-parallelism-limit" {
132+
kubectlLimitCount++
133+
}
134+
}
93135

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))
136+
// Fail if either flag appears more than once
137+
return statusProcessorsCount > 1 || kubectlLimitCount > 1
138+
}).Should(BeFalse())
98139

99-
By("adding a new extra command arg that has the same name as existing parameters")
140+
// 4: Add a repeatable flag multiple times with different values
141+
By("adding a repeatable flag with multiple values")
100142
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
101143
ac.Spec.Controller.ExtraCommandArgs = []string{
102-
"--status-processors",
103-
"15",
104-
"--kubectl-parallelism-limit",
105-
"20",
144+
"--metrics-application-labels", "application.argoproj.io/template-version",
145+
"--metrics-application-labels", "application.argoproj.io/chart-version",
106146
}
107147
})
108148

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

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

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

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

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

182+
// Expect all custom flags to disappear
183+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--metrics-application-labels", 0))
184+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--status-processors 15", 0))
185+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--kubectl-parallelism-limit 20", 0))
186+
Eventually(appControllerSS).ShouldNot(statefulsetFixture.HaveContainerCommandSubstring("--hydrator-enabled", 0))
119187
})
120-
121188
})
189+
122190
})
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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+
23+
argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
24+
argoprojv1a1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
25+
. "github.com/onsi/ginkgo/v2"
26+
. "github.com/onsi/gomega"
27+
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture"
28+
argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd"
29+
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
30+
appsv1 "k8s.io/api/apps/v1"
31+
corev1 "k8s.io/api/core/v1"
32+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33+
"k8s.io/apimachinery/pkg/types"
34+
35+
"sigs.k8s.io/controller-runtime/pkg/client"
36+
)
37+
38+
var _ = Describe("ArgoCD Resource Health Persist", func() {
39+
var (
40+
argoCDName = "example-argocd"
41+
appName = "guestbook"
42+
appNamespace = "guestbook"
43+
)
44+
45+
var (
46+
k8sClient client.Client
47+
ctx context.Context
48+
)
49+
50+
BeforeEach(func() {
51+
fmt.Println("YUOOo")
52+
fixture.EnsureParallelCleanSlate()
53+
54+
k8sClient, _ = fixtureUtils.GetE2ETestKubeClient()
55+
ctx = context.Background()
56+
57+
})
58+
59+
Context("1-120_validate_resource_health_persisted_in_application_status", func() {
60+
It("should persist resource health in Application CR status when configured", func() {
61+
ns, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
62+
defer cleanupFunc()
63+
64+
err := k8sClient.Get(ctx, client.ObjectKey{
65+
Name: ns.Name,
66+
Namespace: ns.Namespace,
67+
}, ns)
68+
Expect(err).Should(BeNil())
69+
70+
By("Creating ArgoCD CR with controller.resource.health.persist=true")
71+
argoCD := &argov1beta1api.ArgoCD{
72+
ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns.Name},
73+
Spec: argov1beta1api.ArgoCDSpec{
74+
Controller: argov1beta1api.ArgoCDApplicationControllerSpec{},
75+
},
76+
}
77+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
78+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
79+
80+
By("Waiting for Application Controller to be ready")
81+
Eventually(func() bool {
82+
deploy := &appsv1.StatefulSet{}
83+
err := k8sClient.Get(ctx, client.ObjectKey{
84+
Name: argoCDName + "-application-controller",
85+
Namespace: ns.Name,
86+
}, deploy)
87+
return err == nil && deploy.Status.ReadyReplicas > 0
88+
}, "1m", "5s").Should(BeTrue())
89+
90+
targetNamespace := &corev1.Namespace{
91+
ObjectMeta: metav1.ObjectMeta{
92+
Name: appNamespace,
93+
Labels: map[string]string{
94+
"argocd.argoproj.io/managed-by": ns.Name,
95+
},
96+
},
97+
}
98+
By("Creating target namespace for Application")
99+
Expect(k8sClient.Create(ctx, targetNamespace)).To(Succeed())
100+
101+
By("Creating ArgoCD Application CR")
102+
app := &argoprojv1a1.Application{
103+
ObjectMeta: metav1.ObjectMeta{
104+
Name: appName,
105+
Namespace: ns.Name,
106+
},
107+
Spec: argoprojv1a1.ApplicationSpec{
108+
Project: "default",
109+
Source: &argoprojv1a1.ApplicationSource{
110+
RepoURL: "https://github.com/Rizwana777/argocd-example-apps",
111+
Path: "guestbook",
112+
TargetRevision: "HEAD",
113+
},
114+
Destination: argoprojv1a1.ApplicationDestination{
115+
Server: "https://kubernetes.default.svc",
116+
Namespace: targetNamespace.Name,
117+
},
118+
SyncPolicy: &argoprojv1a1.SyncPolicy{
119+
Automated: &argoprojv1a1.SyncPolicyAutomated{},
120+
},
121+
},
122+
}
123+
Expect(k8sClient.Create(ctx, app)).To(Succeed())
124+
125+
By("Validating that resource health is persisted in Application CR")
126+
Eventually(func() bool {
127+
var fetched argoprojv1a1.Application
128+
err := k8sClient.Get(ctx, types.NamespacedName{
129+
Name: appName,
130+
Namespace: ns.Name,
131+
}, &fetched)
132+
if err != nil {
133+
return false
134+
}
135+
136+
// Check if application has resources with health information
137+
if len(fetched.Status.Resources) == 0 {
138+
return false
139+
}
140+
141+
for _, res := range fetched.Status.Resources {
142+
if res.Health == nil {
143+
return false
144+
}
145+
if res.Health.Status == "" {
146+
return false
147+
}
148+
}
149+
150+
// Validate resourceHealthSource is NOT present (it is omitted when health is persisted)
151+
return len(fetched.Status.ResourceHealthSource) == 0
152+
}, "3m", "5s").Should(BeTrue())
153+
154+
Expect(k8sClient.Delete(ctx, targetNamespace)).To(Succeed())
155+
})
156+
})
157+
})

0 commit comments

Comments
 (0)