Skip to content

Commit a0bafe5

Browse files
authored
fix: Version override in ArgoCD CR causes operator to use upstream images (#1916)
Signed-off-by: akhil nittala <[email protected]>
1 parent 5468832 commit a0bafe5

File tree

4 files changed

+72
-57
lines changed

4 files changed

+72
-57
lines changed

controllers/argocd/applicationset.go

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -853,30 +853,7 @@ func (r *ReconcileArgoCD) reconcileApplicationSetRoleBinding(cr *argoproj.ArgoCD
853853
}
854854

855855
func getApplicationSetContainerImage(cr *argoproj.ArgoCD) string {
856-
857-
defaultImg, defaultTag := false, false
858-
img := cr.Spec.ApplicationSet.Image
859-
if img == "" {
860-
img = cr.Spec.Image
861-
if img == "" {
862-
img = common.ArgoCDDefaultArgoImage
863-
defaultImg = true
864-
}
865-
}
866-
867-
tag := cr.Spec.ApplicationSet.Version
868-
if tag == "" {
869-
tag = cr.Spec.Version
870-
if tag == "" {
871-
tag = common.ArgoCDDefaultArgoVersion
872-
defaultTag = true
873-
}
874-
}
875-
876-
// If an env var is specified then use that, but don't override the spec values (if they are present)
877-
if e := os.Getenv(common.ArgoCDImageEnvName); e != "" && (defaultTag && defaultImg) {
878-
return e
879-
}
856+
img, tag := GetImageAndTag(common.ArgoCDImageEnvName, cr.Spec.ApplicationSet.Image, cr.Spec.ApplicationSet.Version, cr.Spec.Image, cr.Spec.Version)
880857
return argoutil.CombineImageTag(img, tag)
881858
}
882859

controllers/argocd/util.go

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ package argocd
1717
import (
1818
"bytes"
1919
"context"
20+
"crypto"
2021
"crypto/rand"
22+
"crypto/sha256"
2123
"encoding/base64"
2224
"fmt"
25+
"hash"
2326
"os"
2427
"reflect"
2528
"sort"
@@ -32,6 +35,7 @@ import (
3235
"gopkg.in/yaml.v2"
3336

3437
"github.com/argoproj/argo-cd/v3/util/glob"
38+
"github.com/distribution/reference"
3539
"github.com/go-logr/logr"
3640

3741
"github.com/argoproj-labs/argocd-operator/api/v1alpha1"
@@ -197,22 +201,7 @@ func getArgoApplicationControllerCommand(cr *argoproj.ArgoCD, useTLSForRedis boo
197201

198202
// getArgoContainerImage will return the container image for ArgoCD.
199203
func getArgoContainerImage(cr *argoproj.ArgoCD) string {
200-
defaultTag, defaultImg := false, false
201-
img := cr.Spec.Image
202-
if img == "" {
203-
img = common.ArgoCDDefaultArgoImage
204-
defaultImg = true
205-
}
206-
207-
tag := cr.Spec.Version
208-
if tag == "" {
209-
tag = common.ArgoCDDefaultArgoVersion
210-
defaultTag = true
211-
}
212-
if e := os.Getenv(common.ArgoCDImageEnvName); e != "" && (defaultTag && defaultImg) {
213-
return e
214-
}
215-
204+
img, tag := GetImageAndTag(common.ArgoCDImageEnvName, "", "", cr.Spec.Image, cr.Spec.Version)
216205
return argoutil.CombineImageTag(img, tag)
217206
}
218207

@@ -230,28 +219,70 @@ func getArgoContainerImage(cr *argoproj.ArgoCD) string {
230219
// 4. the default is configured in common.ArgoCDDefaultArgoVersion and
231220
// common.ArgoCDDefaultArgoImage.
232221
func getRepoServerContainerImage(cr *argoproj.ArgoCD) string {
233-
defaultImg, defaultTag := false, false
234-
img := cr.Spec.Repo.Image
235-
if img == "" {
236-
img = cr.Spec.Image
237-
if img == "" {
238-
img = common.ArgoCDDefaultArgoImage
239-
defaultImg = true
240-
}
222+
img, tag := GetImageAndTag(common.ArgoCDImageEnvName, cr.Spec.Repo.Image, cr.Spec.Repo.Version, cr.Spec.Image, cr.Spec.Version)
223+
return argoutil.CombineImageTag(img, tag)
224+
}
225+
226+
// GetImageAndTag determines the image and tag for an ArgoCD component, considering container-level and common-level overrides.
227+
// Priority order: containerSpec > commonSpec > environment variable > defaults
228+
// Returns: image, tag
229+
func GetImageAndTag(envVar, containerSpecImage, containerSpecVersion, commonSpecImage, commonSpecVersion string) (string, string) {
230+
// Start with defaults
231+
image := common.ArgoCDDefaultArgoImage
232+
tag := common.ArgoCDDefaultArgoVersion
233+
234+
// Check if environment variable is set
235+
envVal := os.Getenv(envVar)
236+
237+
// If no spec values are provided and env var is set, use env var as-is
238+
if envVal != "" && containerSpecImage == "" && commonSpecImage == "" &&
239+
containerSpecVersion == "" && commonSpecVersion == "" {
240+
return envVal, ""
241241
}
242242

243-
tag := cr.Spec.Repo.Version
244-
if tag == "" {
245-
tag = cr.Spec.Version
246-
if tag == "" {
247-
tag = common.ArgoCDDefaultArgoVersion
248-
defaultTag = true
243+
// Parse environment variable image if it exists and we need to extract the base image name
244+
if envVal != "" {
245+
baseImageName, err := extractBaseImageName(envVal)
246+
if err != nil {
247+
log.Error(err, "Failed to parse environment variable image", "envVal", envVal)
248+
return "", ""
249+
}
250+
if baseImageName != "" {
251+
image = baseImageName
249252
}
250253
}
251-
if e := os.Getenv(common.ArgoCDImageEnvName); e != "" && (defaultTag && defaultImg) {
252-
return e
254+
255+
// Apply spec overrides with container spec taking precedence over common spec
256+
image = getPriorityValue(containerSpecImage, commonSpecImage, image)
257+
tag = getPriorityValue(containerSpecVersion, commonSpecVersion, tag)
258+
259+
return image, tag
260+
}
261+
262+
// extractBaseImageName extracts the base image name from a full image reference (removing tag/digest)
263+
func extractBaseImageName(imageRef string) (string, error) {
264+
// Handle digest format (image@sha256:...)
265+
crypto.RegisterHash(crypto.SHA256, func() hash.Hash { return sha256.New() })
266+
ref, err := reference.Parse(imageRef)
267+
if err != nil {
268+
return "", err
253269
}
254-
return argoutil.CombineImageTag(img, tag)
270+
var name string
271+
if named, ok := ref.(reference.Named); ok {
272+
name = named.Name()
273+
}
274+
return name, nil
275+
}
276+
277+
// getPriorityValue returns the highest priority value from container spec, common spec, or fallback
278+
func getPriorityValue(containerLevelSpec, commonLevelSpec, fallback string) string {
279+
if containerLevelSpec != "" {
280+
return containerLevelSpec
281+
}
282+
if commonLevelSpec != "" {
283+
return commonLevelSpec
284+
}
285+
return fallback
255286
}
256287

257288
// getArgoRepoResources will return the ResourceRequirements for the Argo CD Repo server container.

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ require (
2828
sigs.k8s.io/controller-runtime v0.21.0
2929
)
3030

31+
require github.com/opencontainers/go-digest v1.0.0 // indirect
32+
3133
require (
3234
github.com/beorn7/perks v1.0.1 // indirect
3335
github.com/blang/semver/v4 v4.0.0 // indirect
3436
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3537
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
38+
github.com/distribution/reference v0.6.0
3639
github.com/dlclark/regexp2 v1.11.5 // indirect
3740
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
3841
github.com/evanphx/json-patch/v5 v5.9.11 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
3030
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
3131
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3232
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
33+
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
34+
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
3335
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
3436
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
3537
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
@@ -183,6 +185,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
183185
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
184186
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
185187
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
188+
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
189+
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
186190
github.com/openshift/api v0.0.0-20200324160301-f91f52aea878/go.mod h1:7k3+uZYOir97walbYUqApHUA2OPhkQpVJHt0n7GJ6P4=
187191
github.com/openshift/api v0.0.0-20240906151052-5d963dce87aa h1:RMI6Xa+l8KriyoxsRO/swMDPyCwrxJNA9H67K0Jod/w=
188192
github.com/openshift/api v0.0.0-20240906151052-5d963dce87aa/go.mod h1:yimSGmjsI+XF1mr+AKBs2//fSXIOhhetHGbMlBEfXbs=

0 commit comments

Comments
 (0)