Skip to content

Commit 2de1a48

Browse files
downstream fix: added mapping of timeout.reconciliation to env var (#1049)
* downstream fix: added mapping of timeout.reconciliation to env var Signed-off-by: Alka Kumari <[email protected]> * fixed panick error in ginkgo test Signed-off-by: Alka Kumari <[email protected]> --------- Signed-off-by: Alka Kumari <[email protected]>
1 parent 8a4b5be commit 2de1a48

File tree

4 files changed

+264
-3
lines changed

4 files changed

+264
-3
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24.6
44

55
require (
66
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251105123110-0c547c7a7765
7-
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20251212100514-ffddb3445337
7+
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260104093047-07f678ea4720
88
github.com/argoproj/argo-cd/v3 v3.1.9
99
github.com/argoproj/gitops-engine v0.7.1-0.20250905160054-e48120133eec
1010
github.com/go-logr/logr v1.4.3

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
3131
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
3232
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251105123110-0c547c7a7765 h1:zVN+W/nQrRB/kB63YcvcCseuiE//sEzNw6Oa8rqiFOs=
3333
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251105123110-0c547c7a7765/go.mod h1:WPyZkNHZjir/OTt8mrRwcUZKe1euHrHPJsRv1Wp/F/0=
34-
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20251212100514-ffddb3445337 h1:lGkZs/iUHnc1JTPmg9DQH3ADZ4rBj21LuezYfr/5IKg=
35-
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20251212100514-ffddb3445337/go.mod h1:tugRb82zAQXSsQfogeBkNUfl5ffdPAAD5nk/9eRAUC8=
34+
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260104093047-07f678ea4720 h1:4zz1AG1DjyoUdJiyQ0XpWu5FK3R19CL9jEUbHiiuYAU=
35+
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260104093047-07f678ea4720/go.mod h1:tugRb82zAQXSsQfogeBkNUfl5ffdPAAD5nk/9eRAUC8=
3636
github.com/argoproj/argo-cd/v3 v3.1.9 h1:9P9vJKo1RGWu6mtQnGu61r+0h3XKlA2j3kVhwogUQ/0=
3737
github.com/argoproj/argo-cd/v3 v3.1.9/go.mod h1:ZHb/LOz/hr88VWMJiVTd8DGYL7MheHCAT8S6DgYOBFo=
3838
github.com/argoproj/gitops-engine v0.7.1-0.20250905160054-e48120133eec h1:rNAwbRQFvRIuW/e2bU+B10mlzghYXsnwZedYeA7Drz4=

test/openshift/e2e/ginkgo/fixture/statefulset/fixture.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"reflect"
66
"strings"
7+
"time"
78

89
//lint:ignore ST1001 "This is a common practice in Gomega tests for readability."
910
. "github.com/onsi/ginkgo/v2" //nolint:all
@@ -38,6 +39,15 @@ func Update(obj *appsv1.StatefulSet, modify func(*appsv1.StatefulSet)) {
3839
Expect(err).ToNot(HaveOccurred())
3940
}
4041

42+
func Restart(obj *appsv1.StatefulSet) {
43+
Update(obj, func(ss *appsv1.StatefulSet) {
44+
if ss.Spec.Template.Annotations == nil {
45+
ss.Spec.Template.Annotations = make(map[string]string)
46+
}
47+
ss.Spec.Template.Annotations["kubectl.kubernetes.io/restartedAt"] = time.Now().Format(time.RFC3339)
48+
})
49+
}
50+
4151
func HaveReplicas(replicas int) matcher.GomegaMatcher {
4252
return fetchStatefulSet(func(ss *appsv1.StatefulSet) bool {
4353
GinkgoWriter.Println("StatefulSet HaveReplicas:", "expected: ", replicas, "actual: ", ss.Status.Replicas)
@@ -258,6 +268,35 @@ func HaveContainerWithEnvVar(envKey string, envValue string, containerIndex int)
258268
})
259269
}
260270

271+
// HaveContainerWithEnvVarFromConfigMap checks if a container has an env var that references a ConfigMap key
272+
func HaveContainerWithEnvVarFromConfigMap(envKey string, configMapName string, configMapKey string, containerIndex int) matcher.GomegaMatcher {
273+
return fetchStatefulSet(func(ss *appsv1.StatefulSet) bool {
274+
275+
containers := ss.Spec.Template.Spec.Containers
276+
277+
if len(containers) <= containerIndex {
278+
GinkgoWriter.Println("current container slice has length", len(containers), "index is", containerIndex)
279+
return false
280+
}
281+
282+
container := containers[containerIndex]
283+
284+
for _, env := range container.Env {
285+
if env.Name == envKey {
286+
if env.ValueFrom != nil && env.ValueFrom.ConfigMapKeyRef != nil {
287+
ref := env.ValueFrom.ConfigMapKeyRef
288+
GinkgoWriter.Println("HaveContainerWithEnvVarFromConfigMap - Key:", envKey,
289+
"Expected ConfigMap:", configMapName, "Key:", configMapKey,
290+
"Actual ConfigMap:", ref.Name, "Key:", ref.Key)
291+
return ref.Name == configMapName && ref.Key == configMapKey
292+
}
293+
}
294+
}
295+
296+
return false
297+
})
298+
}
299+
261300
// This is intentionally NOT exported, for now. Create another function in this file/package that calls this function, and export that.
262301
func fetchStatefulSet(f func(*appsv1.StatefulSet) bool) matcher.GomegaMatcher {
263302

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
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+
"time"
22+
23+
argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
24+
. "github.com/onsi/ginkgo/v2"
25+
. "github.com/onsi/gomega"
26+
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture"
27+
argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd"
28+
configmapFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/configmap"
29+
k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s"
30+
statefulsetFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/statefulset"
31+
fixtureUtils "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
32+
appsv1 "k8s.io/api/apps/v1"
33+
corev1 "k8s.io/api/core/v1"
34+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35+
36+
"sigs.k8s.io/controller-runtime/pkg/client"
37+
)
38+
39+
var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
40+
41+
Context("1-122_validate_argocd_reconciliation_timeout environment variable", func() {
42+
43+
var (
44+
k8sClient client.Client
45+
ctx context.Context
46+
ns *corev1.Namespace
47+
cleanupFunc func()
48+
)
49+
50+
BeforeEach(func() {
51+
fixture.EnsureParallelCleanSlate()
52+
k8sClient, _ = fixtureUtils.GetE2ETestKubeClient()
53+
ctx = context.Background()
54+
})
55+
56+
AfterEach(func() {
57+
fixture.OutputDebugOnFail(ns)
58+
59+
if cleanupFunc != nil {
60+
cleanupFunc()
61+
}
62+
})
63+
64+
It("should set ARGOCD_RECONCILIATION_TIMEOUT with appSync value", func() {
65+
66+
By("creating simple namespace-scoped Argo CD instance")
67+
ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
68+
69+
argoCD := &argov1beta1api.ArgoCD{
70+
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name},
71+
Spec: argov1beta1api.ArgoCDSpec{
72+
Controller: argov1beta1api.ArgoCDApplicationControllerSpec{
73+
AppSync: &metav1.Duration{Duration: time.Minute * 10},
74+
},
75+
},
76+
}
77+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
78+
79+
By("waiting for ArgoCD CR to be reconciled and the instance to be ready")
80+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
81+
82+
ss := &appsv1.StatefulSet{
83+
ObjectMeta: metav1.ObjectMeta{
84+
Name: "argocd-application-controller",
85+
Namespace: ns.Name,
86+
},
87+
}
88+
Eventually(ss).Should(k8sFixture.ExistByName())
89+
Eventually(ss).Should(statefulsetFixture.HaveReplicas(1))
90+
Eventually(ss).Should(statefulsetFixture.HaveReadyReplicas(1))
91+
92+
By("verifying env var is added to argocd-application-controller, and that other env vars are still present")
93+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVar("ARGOCD_RECONCILIATION_TIMEOUT", "600s", 0))
94+
95+
Expect(len(ss.Spec.Template.Spec.Containers[0].Env)).To(BeNumerically(">", 1))
96+
97+
By("Updating appSync to 5 minutes")
98+
argoCD.Spec.Controller.AppSync = &metav1.Duration{Duration: time.Minute * 5}
99+
Expect(k8sClient.Update(ctx, argoCD)).To(Succeed())
100+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
101+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVar("ARGOCD_RECONCILIATION_TIMEOUT", "300s", 0))
102+
103+
})
104+
105+
It("should set environment variable ARGOCD_RECONCILIATION_TIMEOUT with timeout.reconciliation value in configmap", func() {
106+
107+
By("creating simple namespace-scoped Argo CD instance")
108+
ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
109+
110+
argoCD := &argov1beta1api.ArgoCD{
111+
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name},
112+
Spec: argov1beta1api.ArgoCDSpec{
113+
ExtraConfig: map[string]string{"timeout.reconciliation": "10m"},
114+
},
115+
}
116+
117+
By("waiting for ArgoCD CR to be reconciled and the instance to be ready")
118+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
119+
120+
By("Fetching ConfigMap and verifying timeout.reconciliation value")
121+
argocdCM := &corev1.ConfigMap{
122+
ObjectMeta: metav1.ObjectMeta{Name: "argocd-cm", Namespace: ns.Name},
123+
}
124+
Eventually(argocdCM).Should(configmapFixture.HaveStringDataKeyValue("timeout.reconciliation", "10m"))
125+
126+
By("waiting for StatefulSet to be ready")
127+
ss := &appsv1.StatefulSet{
128+
ObjectMeta: metav1.ObjectMeta{
129+
Name: "argocd-application-controller",
130+
Namespace: ns.Name,
131+
},
132+
}
133+
Eventually(ss).Should(k8sFixture.ExistByName())
134+
Eventually(ss).Should(statefulsetFixture.HaveReplicas(1))
135+
Eventually(ss).Should(statefulsetFixture.HaveReadyReplicas(1))
136+
137+
By("verifying env var is added to example-argocd-application-controller, and that other env vars are still present")
138+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVarFromConfigMap(
139+
"ARGOCD_RECONCILIATION_TIMEOUT",
140+
"argocd-cm",
141+
"timeout.reconciliation",
142+
0,
143+
))
144+
145+
By("Updating timeout.reconciliation to 5 minutes and waiting for ArgoCD CR to be reconciled and the instance to be ready")
146+
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
147+
ac.Spec.ExtraConfig["timeout.reconciliation"] = "5m"
148+
})
149+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
150+
151+
Eventually(argocdCM).Should(configmapFixture.HaveStringDataKeyValue("timeout.reconciliation", "5m"))
152+
153+
By("waiting for StatefulSet to be ready after restart")
154+
statefulsetFixture.Restart(ss)
155+
Eventually(ss, "3m", "5s").Should(statefulsetFixture.HaveReadyReplicas(1))
156+
ss = &appsv1.StatefulSet{
157+
ObjectMeta: metav1.ObjectMeta{
158+
Name: "argocd-application-controller",
159+
Namespace: ns.Name,
160+
},
161+
}
162+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVarFromConfigMap(
163+
"ARGOCD_RECONCILIATION_TIMEOUT",
164+
"argocd-cm",
165+
"timeout.reconciliation",
166+
0,
167+
))
168+
})
169+
170+
It("Validate the precedence of the appSync value over the timeout.reconciliation value in configmap", func() {
171+
ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()
172+
173+
By("creating ArgoCD CR with appSync value and timeout.reconciliation value in configmap")
174+
argoCD := &argov1beta1api.ArgoCD{
175+
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name},
176+
Spec: argov1beta1api.ArgoCDSpec{
177+
Controller: argov1beta1api.ArgoCDApplicationControllerSpec{
178+
AppSync: &metav1.Duration{Duration: time.Minute * 10},
179+
},
180+
ExtraConfig: map[string]string{"timeout.reconciliation": "15m"},
181+
},
182+
}
183+
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
184+
185+
By("waiting for ArgoCD CR to be reconciled and the instance to be ready")
186+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
187+
188+
ss := &appsv1.StatefulSet{
189+
ObjectMeta: metav1.ObjectMeta{
190+
Name: "argocd-application-controller",
191+
Namespace: ns.Name,
192+
},
193+
}
194+
Eventually(ss).Should(k8sFixture.ExistByName())
195+
Eventually(ss).Should(statefulsetFixture.HaveReadyReplicas(1))
196+
197+
By("verifying env var is added to argocd-application-controller and the appSync value is used")
198+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVar("ARGOCD_RECONCILIATION_TIMEOUT", "600s", 0))
199+
200+
By("Removing appSync value and waiting for ArgoCD CR to be reconciled and the instance to be ready")
201+
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
202+
ac.Spec.Controller.AppSync = nil
203+
})
204+
Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable())
205+
statefulsetFixture.Restart(ss)
206+
Eventually(ss, "3m", "5s").Should(statefulsetFixture.HaveReadyReplicas(1))
207+
By("Fetching ConfigMap and verifying timeout.reconciliation value")
208+
argocdCM := &corev1.ConfigMap{
209+
ObjectMeta: metav1.ObjectMeta{Name: "argocd-cm", Namespace: ns.Name},
210+
}
211+
Eventually(argocdCM).Should(configmapFixture.HaveStringDataKeyValue("timeout.reconciliation", "15m"))
212+
By("verifying env var is added to example-argocd-application-controller and the timeout.reconciliation value is used")
213+
Eventually(ss).Should(statefulsetFixture.HaveContainerWithEnvVarFromConfigMap(
214+
"ARGOCD_RECONCILIATION_TIMEOUT",
215+
"argocd-cm",
216+
"timeout.reconciliation",
217+
0,
218+
))
219+
220+
})
221+
})
222+
})

0 commit comments

Comments
 (0)