argoproj-labs/argocd-image-updater

App-of-apps annotation enhancement

aqeelat opened this issue · 2 comments

Is your feature request related to a problem? Please describe.
When deploying charts with multiple images (such as with app-of-apps), each image must be specified in the annotation. The number of annotations grows a lot when using helm. Essentially, you'd need at least 2x+1 annotations.

annotations:
  argocd-image-updater.argoproj.io/update-strategy: digest
  argocd-image-updater.argoproj.io/image-list: |
    one=one:latest
    two=two:latest
    three=three:latest
  argocd-image-updater.argoproj.io/one.helm.image-name: one.image.name
  argocd-image-updater.argoproj.io/one.helm.image-tag: one.image.tag
  argocd-image-updater.argoproj.io/two.helm.image-name: two.image.name
  argocd-image-updater.argoproj.io/two.helm.image-tag: two.image.tag
  argocd-image-updater.argoproj.io/three.helm.image-name: server.image.name
  argocd-image-updater.argoproj.io/three.helm.image-tag: server.image.tag

Describe the solution you'd like
Using a placeholder for the image aliases, with the ability to override it if you want to opt out of the new default method.

This can be done in multiple ways, but essentially, they goal is to give the user the ability to share common annotations between an indeterminate number of image aliases.

For example:

annotations:
  argocd-image-updater.argoproj.io/update-strategy: digest
  argocd-image-updater.argoproj.io/image-list: |
    $one=one:latest
    $two=two:latest
    three=three:latest
  argocd-image-updater.argoproj.io/$.helm.image-name: $.image.name
  argocd-image-updater.argoproj.io/$.helm.image-tag: $.image.tag
  argocd-image-updater.argoproj.io/three.helm.image-name: server.image.name
  argocd-image-updater.argoproj.io/three.helm.image-tag: server.image.tag

Here, we prefixed the aliases with a $. The controller then should just replace the $ in the annotations with the actual image alias.
They're essentially equivalent to:

  argocd-image-updater.argoproj.io/one.helm.image-name: one.image.name
  argocd-image-updater.argoproj.io/one.helm.image-tag: one.image.tag
  argocd-image-updater.argoproj.io/two.helm.image-name: two.image.name
  argocd-image-updater.argoproj.io/two.helm.image-tag: two.image.tag
  argocd-image-updater.argoproj.io/three.helm.image-name: server.image.name
  argocd-image-updater.argoproj.io/three.helm.image-tag: server.image.tag

I'm not a go developer but I assume implementing this could be done by adding the logic below to this group of methods:

  1. if img.ImageAlias starts with $
    // GetParameterHelmImageName gets the value for image-name option for the image
    // from a set of annotations
    func (img *ContainerImage) GetParameterHelmImageName(annotations map[string]string) string {
    key := fmt.Sprintf(common.HelmParamImageNameAnnotation, img.normalizedSymbolicName())
    val, ok := annotations[key]
    if !ok {
    return ""
    }
    return val
    }
If img.ImageAlias[0] == '$':
  key =  fmt.Sprintf(common.HelmParamImageNameAnnotation, '$')
  if key in annotations:
        path = annotations[key]
        return fmt.Sprintf('%s%s', img.ImageAlias[1:], path[1:])

This can be further enhanced by supporting multiple alias groups:

annotations:
  argocd-image-updater.argoproj.io/update-strategy: digest
  argocd-image-updater.argoproj.io/image-list: |
    $aliasGroup1.one=one:latest
    $aliasGroup1.two=two:latest
    $aliasGroup2.three=three:latest
    $aliasGroup2.four=four:latest
  argocd-image-updater.argoproj.io/$aliasGroup1.helm.image-name: $.image.name
  argocd-image-updater.argoproj.io/$aliasGroup1.helm.image-tag: $.image.tag
  argocd-image-updater.argoproj.io/$aliasGroup2.helm.image-name: $image.name # the dot is removed intentionally
  argocd-image-updater.argoproj.io/$aliasGroup2.helm.image-tag: $image.tag # the dot is removed intentionally

Describe alternatives you've considered

Additional context
I don't know enough Go to open a PR but I would like to help with any discussions related to this feature.

@aqeelat thanks for the proposal! Just share my initial thoughts, and would love to get more input from other community memebers.

There is additional complexity when adding this templating capability. The project needs to maintain this logic, users need to understand the syntax, and app developers need make sure the image-name, image-tag, image-spec values are in sync with values file. Using an image alias holder makes it less direct to link the annotations to fields in values file.