Skip to content

Commit 89e1158

Browse files
authored
Merge PR #1395: Merge release v1.0.2 commits into release-1.0
This PR merges all commits prepared for the v1.0.2 release into the release-1.0 branch.
2 parents cc39181 + baa8615 commit 89e1158

36 files changed

+752
-145
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,14 @@ Add any other context about the problem here.
2222
**Version**
2323
Please tell us about the version you encountered the issue with
2424

25+
**Regression**
26+
Does this issue apply to (check all that apply):
27+
28+
- [ ] Annotation-based configuration (versions starting with `0`, e.g., `0.17.0`)
29+
- [ ] CRD-based configuration (versions starting with `1`, e.g., `1.0.0`)
30+
31+
**Latest working version (if applicable)**
32+
If you are reporting a regression, please specify the last version where this feature worked as expected.
33+
2534
**Logs**
2635
Please paste any relevant logs here

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,11 @@ A clear and concise description of what you want to happen.
1616
**Describe alternatives you've considered**
1717
A clear and concise description of any alternative solutions or features you've considered.
1818

19+
**Version**
20+
This feature request applies to (check all that apply):
21+
22+
- [ ] Annotation-based configuration (versions starting with `0`, e.g., `0.17.0`)
23+
- [ ] CRD-based configuration (versions starting with `1`, e.g., `1.0.0`)
24+
1925
**Additional context**
2026
Add any other context or screenshots about the feature request here.

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
IMAGE_UPDATER_CONTROLLER_NAMESPACE?=argocd
12
IMAGE_NAMESPACE?=quay.io/argoprojlabs
23
IMAGE_NAME=argocd-image-updater
34
ifdef IMAGE_NAMESPACE
@@ -196,11 +197,11 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified
196197
.PHONY: deploy
197198
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
198199
cd config/manager && $(KUSTOMIZE) edit set image argocd-image-updater-controller=${IMG}
199-
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
200+
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -n ${IMAGE_UPDATER_CONTROLLER_NAMESPACE} -f -
200201

201202
.PHONY: undeploy
202203
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
203-
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
204+
$(KUSTOMIZE) build config/default | $(KUBECTL) delete -n ${IMAGE_UPDATER_CONTROLLER_NAMESPACE} --ignore-not-found=$(ignore-not-found) -f -
204205

205206
##@ Dependencies
206207

@@ -218,7 +219,7 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
218219

219220
## Tool Versions
220221
KUSTOMIZE_VERSION ?= v5.4.3
221-
CONTROLLER_TOOLS_VERSION ?= v0.16.1
222+
CONTROLLER_TOOLS_VERSION ?= v0.19.0
222223
ENVTEST_VERSION ?= release-0.19
223224
GOLANGCI_LINT_VERSION ?= v2.5.0
224225

cmd/run.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,16 @@ This enables a CRD-driven approach to automated image updates with Argo CD.
9999
WithValues(logrusFieldsToLogrValues(common.ControllerLogFields)...)
100100

101101
setupLogger.Info("Controller runtime logger initialized.", "setAppLogLevel", cfg.LogLevel)
102-
setupLogger.Info("starting",
103-
"app", version.BinaryName()+": "+version.Version(),
102+
logFields := []interface{}{
103+
"app", version.BinaryName() + ": " + version.Version(),
104104
"loglevel", strings.ToUpper(cfg.LogLevel),
105105
"interval", argocd.GetPrintableInterval(cfg.CheckInterval),
106106
"healthPort", probeAddr,
107-
)
107+
}
108+
if cfg.ArgocdNamespace != "" {
109+
logFields = append(logFields, "argocdNamespace", cfg.ArgocdNamespace)
110+
}
111+
setupLogger.Info("starting", logFields...)
108112

109113
// Create context with signal handling
110114
ctx := ctrl.SetupSignalHandler()
@@ -170,6 +174,16 @@ This enables a CRD-driven approach to automated image updates with Argo CD.
170174
return err
171175
}
172176

177+
// isLeader is an atomic bool that will be set to true when the controller
178+
// becomes the leader.
179+
var isLeader atomic.Bool
180+
181+
// Start a goroutine that sets isLeader to true when leadership is acquired.
182+
go func() {
183+
<-mgr.Elected()
184+
isLeader.Store(true)
185+
}()
186+
173187
// Add the CacheWarmer as a Runnable to the manager.
174188
setupLogger.Info("Adding cache warmer to the manager.")
175189
warmupState := &WarmupStatus{
@@ -231,11 +245,11 @@ This enables a CRD-driven approach to automated image updates with Argo CD.
231245
}
232246

233247
if err := mgr.AddReadyzCheck("warmup-check", func(req *http.Request) error {
234-
if !warmupState.isCacheWarmed.Load() {
235-
// If the cache is not yet warmed, the check fails.
248+
// If we are the leader, we are ready only if the cache is warmed.
249+
if isLeader.Load() && !warmupState.isCacheWarmed.Load() {
236250
return fmt.Errorf("cache is not yet warmed")
237251
}
238-
// Once warmed, the check passes.
252+
// If we are not the leader, we are always ready.
239253
return nil
240254
}); err != nil {
241255
setupLogger.Error(err, "unable to set up ready check")
@@ -285,7 +299,7 @@ This enables a CRD-driven approach to automated image updates with Argo CD.
285299
controllerCmd.Flags().StringVar(&cfg.RegistriesConf, "registries-conf-path", common.DefaultRegistriesConfPath, "path to registries configuration file")
286300
controllerCmd.Flags().IntVar(&cfg.MaxConcurrentApps, "max-concurrent-apps", env.ParseNumFromEnv("MAX_CONCURRENT_APPS", 10, 1, 100), "maximum number of ArgoCD applications that can be updated concurrently (must be >= 1)")
287301
controllerCmd.Flags().IntVar(&MaxConcurrentReconciles, "max-concurrent-reconciles", env.ParseNumFromEnv("MAX_CONCURRENT_RECONCILES", 1, 1, 10), "maximum number of concurrent Reconciles which can be run (must be >= 1)")
288-
controllerCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", "", "namespace where ArgoCD runs in (current namespace by default)")
302+
controllerCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", env.GetStringVal("ARGOCD_NAMESPACE", ""), "namespace where ArgoCD runs in (controller namespace by default)")
289303
controllerCmd.Flags().BoolVar(&warmUpCache, "warmup-cache", true, "whether to perform a cache warm-up on startup")
290304
controllerCmd.Flags().BoolVar(&cfg.DisableKubeEvents, "disable-kube-events", env.GetBoolVal("IMAGE_UPDATER_KUBE_EVENTS", false), "Disable kubernetes events")
291305

@@ -420,6 +434,8 @@ func (ws *WebhookServerRunnable) Start(ctx context.Context) error {
420434
return ws.webhookServer.Start(ctx)
421435
}
422436

437+
// NeedLeaderElection tells the manager that this runnable should only be
438+
// run on the leader replica.
423439
func (ws *WebhookServerRunnable) NeedLeaderElection() bool {
424440
return true
425441
}

cmd/run_test.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"os"
99
"strconv"
10+
"sync/atomic"
1011
"testing"
1112
"time"
1213

@@ -49,7 +50,7 @@ func TestNewRunCommand(t *testing.T) {
4950
asser.Equal(common.DefaultRegistriesConfPath, controllerCommand.Flag("registries-conf-path").Value.String())
5051
asser.Equal(strconv.Itoa(env.ParseNumFromEnv("MAX_CONCURRENT_APPS", 10, 1, 100)), controllerCommand.Flag("max-concurrent-apps").Value.String())
5152
asser.Equal(strconv.Itoa(env.ParseNumFromEnv("MAX_CONCURRENT_RECONCILES", 1, 1, 10)), controllerCommand.Flag("max-concurrent-reconciles").Value.String())
52-
asser.Equal("", controllerCommand.Flag("argocd-namespace").Value.String())
53+
asser.Equal(env.GetStringVal("ARGOCD_NAMESPACE", ""), controllerCommand.Flag("argocd-namespace").Value.String())
5354
asser.Equal("true", controllerCommand.Flag("warmup-cache").Value.String())
5455
asser.Equal(env.GetStringVal("GIT_COMMIT_USER", "argocd-image-updater"), controllerCommand.Flag("git-commit-user").Value.String())
5556
asser.Equal(env.GetStringVal("GIT_COMMIT_EMAIL", "noreply@argoproj.io"), controllerCommand.Flag("git-commit-email").Value.String())
@@ -340,3 +341,68 @@ func TestReadyzCheckWithWarmupStatus(t *testing.T) {
340341
assert.Equal(t, "cache is not yet warmed", err.Error())
341342
})
342343
}
344+
345+
// Assisted-by: Gemini AI
346+
// TestLeadershipAwareReadyzCheck verifies the behavior of the leadership-aware readiness probe.
347+
func TestLeadershipAwareReadyzCheck(t *testing.T) {
348+
testCases := []struct {
349+
name string
350+
isLeader bool
351+
isWarmed bool
352+
expectError bool
353+
errorMsg string
354+
}{
355+
{
356+
name: "Leader and not warmed",
357+
isLeader: true,
358+
isWarmed: false,
359+
expectError: true,
360+
errorMsg: "cache is not yet warmed",
361+
},
362+
{
363+
name: "Leader and warmed",
364+
isLeader: true,
365+
isWarmed: true,
366+
expectError: false,
367+
},
368+
{
369+
name: "Not leader and not warmed",
370+
isLeader: false,
371+
isWarmed: false,
372+
expectError: false,
373+
},
374+
{
375+
name: "Not leader and warmed",
376+
isLeader: false,
377+
isWarmed: true,
378+
expectError: false,
379+
},
380+
}
381+
382+
for _, tc := range testCases {
383+
t.Run(tc.name, func(t *testing.T) {
384+
var isLeader atomic.Bool
385+
isLeader.Store(tc.isLeader)
386+
387+
status := &WarmupStatus{Done: make(chan struct{})}
388+
status.isCacheWarmed.Store(tc.isWarmed)
389+
390+
// This is the readiness check logic from cmd/run.go
391+
readinessCheck := func(req *http.Request) error {
392+
if isLeader.Load() && !status.isCacheWarmed.Load() {
393+
return fmt.Errorf("cache is not yet warmed")
394+
}
395+
return nil
396+
}
397+
398+
err := readinessCheck(nil)
399+
400+
if tc.expectError {
401+
assert.Error(t, err)
402+
assert.Equal(t, tc.errorMsg, err.Error())
403+
} else {
404+
assert.NoError(t, err)
405+
}
406+
})
407+
}
408+
}

cmd/webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Supported registries:
7474
webhookCmd.Flags().StringVar(&cfg.RegistriesConf, "registries-conf-path", common.DefaultRegistriesConfPath, "path to registries configuration file")
7575
webhookCmd.Flags().IntVar(&cfg.MaxConcurrentApps, "max-concurrent-apps", env.ParseNumFromEnv("MAX_CONCURRENT_APPS", 10, 1, 100), "maximum number of ArgoCD applications that can be updated concurrently (must be >= 1)")
7676
webhookCmd.Flags().IntVar(&MaxConcurrentUpdaters, "max-concurrent-updaters", env.ParseNumFromEnv("MAX_CONCURRENT_UPDATERS", 1, 1, 10), "maximum number of concurrent ImageUpdater CRs that can be processed (must be >= 1)")
77-
webhookCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", "", "namespace where ArgoCD runs in (current namespace by default)")
77+
webhookCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", env.GetStringVal("ARGOCD_NAMESPACE", ""), "namespace where ArgoCD runs in (controller namespace by default)")
7878

7979
webhookCmd.Flags().StringVar(&cfg.GitCommitUser, "git-commit-user", env.GetStringVal("GIT_COMMIT_USER", "argocd-image-updater"), "Username to use for Git commits")
8080
webhookCmd.Flags().StringVar(&cfg.GitCommitMail, "git-commit-email", env.GetStringVal("GIT_COMMIT_EMAIL", "noreply@argoproj.io"), "E-Mail address to use for Git commits")

cmd/webhook_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestNewWebhookCommand(t *testing.T) {
2929
asser.Equal(common.DefaultRegistriesConfPath, controllerCommand.Flag("registries-conf-path").Value.String())
3030
asser.Equal(strconv.Itoa(env.ParseNumFromEnv("MAX_CONCURRENT_APPS", 10, 1, 100)), controllerCommand.Flag("max-concurrent-apps").Value.String())
3131
asser.Equal(strconv.Itoa(env.ParseNumFromEnv("MAX_CONCURRENT_UPDATERS", 1, 1, 10)), controllerCommand.Flag("max-concurrent-updaters").Value.String())
32-
asser.Equal("", controllerCommand.Flag("argocd-namespace").Value.String())
32+
asser.Equal(env.GetStringVal("ARGOCD_NAMESPACE", ""), controllerCommand.Flag("argocd-namespace").Value.String())
3333
asser.Equal(env.GetStringVal("GIT_COMMIT_USER", "argocd-image-updater"), controllerCommand.Flag("git-commit-user").Value.String())
3434
asser.Equal(env.GetStringVal("GIT_COMMIT_EMAIL", "noreply@argoproj.io"), controllerCommand.Flag("git-commit-email").Value.String())
3535
asser.Equal(env.GetStringVal("GIT_COMMIT_SIGNING_KEY", ""), controllerCommand.Flag("git-commit-signing-key").Value.String())

config/crd/bases/argocd-image-updater.argoproj.io_imageupdaters.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.16.1
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: imageupdaters.argocd-image-updater.argoproj.io
88
spec:
99
group: argocd-image-updater.argoproj.io

config/default/kustomization.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# Adds namespace to all resources.
2-
namespace: argocd-image-updater-system
3-
41
# Labels to add to all resources and selectors.
52
#labels:
63
#- includeSelectors: true

config/default/metrics_service.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ metadata:
66
app.kubernetes.io/name: argocd-image-updater
77
app.kubernetes.io/managed-by: kustomize
88
name: argocd-image-updater-controller-metrics-service
9-
namespace: argocd-image-updater-system
109
spec:
1110
ports:
1211
- name: https

0 commit comments

Comments
 (0)