@@ -17,9 +17,12 @@ package argocd
1717import (
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.
199203func 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.
232221func 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.
0 commit comments