summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjannfis <jann@mistrust.net>2020-09-27 14:24:30 +0200
committerGitHub <noreply@github.com>2020-09-27 14:24:30 +0200
commit330fa57fd51331b911901d5a31b6956cb080ba0e (patch)
tree4251a3459449b8f1444147c7ed91344297089719
parent02d580fc6805963e89632fbad3782cf5bfa1e80e (diff)
feat: Allow ignoring set of tags (#101)
* feat: Allow ignoring set of tags * Fix a typo in symbol name * Rename symbol * err must be nil; also print trace message * Update documentation * Update documentation * String is already trimmed
-rw-r--r--docs/configuration/images.md25
-rw-r--r--pkg/argocd/update.go1
-rw-r--r--pkg/common/constants.go5
-rw-r--r--pkg/image/options.go21
-rw-r--r--pkg/image/options_test.go15
-rw-r--r--pkg/image/version.go14
-rw-r--r--pkg/registry/registry.go4
7 files changed, 81 insertions, 4 deletions
diff --git a/docs/configuration/images.md b/docs/configuration/images.md
index 6284d53..52212a7 100644
--- a/docs/configuration/images.md
+++ b/docs/configuration/images.md
@@ -144,6 +144,30 @@ to prevent considering (and possibly update to) the wrong tags by accident.
If the annotation is not specified, a match function `any` will be used to match
the tag names, effectively performing no filtering at all.
+## Ignoring certain tags
+
+If you want to ignore certain tags from the registry for any given image, you
+can define a comma separated list of glob-like patterns using the following
+annotation:
+
+```yaml
+argocd-image-updater.argoproj.io/<image_name>.ignore-tags: <pattern1>[, <pattern2>, ...]
+```
+
+You can use glob patterns as described in this
+[documentation](https://golang.org/pkg/path/filepath/#Match)
+
+If you want to disable updating an image temporarily, without removing all of
+the configuration, you can do so by just ignoring all tags, effectively
+preventing the image updater to consider any of the tags returned from the
+registry:
+
+```yaml
+argocd-image-updater.argoproj.io/<image_name>.ignore-tags: "*"
+```
+
+Please note that regular expressions are not supported to be used for patterns.
+
## Specifying pull secrets
There are generally two ways on how to specify pull secrets for Argo CD Image
@@ -318,6 +342,7 @@ must be prefixed with `argocd-image-updater.argoproj.io`.
|`image-list`|*none*|Comma separated list of images to consider for update|
|`<image_alias>.update-strategy`|`semver`|The update strategy to be used for the image|
|`<image_alias>.tag-match`|*any*|A function to match tag names from registry against to be considered for update|
+|`<image_alias>.ignore-tags`|*none*|A comma-separated list of glob patterns that when match ignore a certain tag from the registry|
|`<image_alias>.pull-secret`|*none*|A reference to a secret to be used as registry credentials for this image|
|`<image_alias>.helm.image-spec`|*none*|Name of the Helm parameter to specify the canonical name of the image, i.e. holds `image/name:1.0`. If this is set, other Helm parameter related options will be ignored.|
|`<image_alias>.helm.image-name`|`image.name`|Name of the Helm parameter used for specifying the image name, i.e. holds `image/name`|
diff --git a/pkg/argocd/update.go b/pkg/argocd/update.go
index c52aa09..cf68011 100644
--- a/pkg/argocd/update.go
+++ b/pkg/argocd/update.go
@@ -75,6 +75,7 @@ func UpdateApplication(newRegFn registry.NewRegistryClient, argoClient ArgoCD, k
vc.SortMode = applicationImage.GetParameterUpdateStrategy(curApplication.Application.Annotations)
vc.MatchFunc, vc.MatchArgs = applicationImage.GetParameterMatch(curApplication.Application.Annotations)
+ vc.IgnoreList = applicationImage.GetParameterIgnoreTags(curApplication.Application.Annotations)
// The endpoint can provide default credentials for pulling images
err = rep.SetEndpointCredentials(kubeClient)
diff --git a/pkg/common/constants.go b/pkg/common/constants.go
index 76bf2bb..847fe39 100644
--- a/pkg/common/constants.go
+++ b/pkg/common/constants.go
@@ -28,8 +28,9 @@ const (
// Upgrade strategy related annotations
const (
- MatchOptionAnnotation = ImageUpdaterAnnotationPrefix + "/%s.tag-match"
- UpdateStrategyAnnotation = ImageUpdaterAnnotationPrefix + "/%s.update-strategy"
+ MatchOptionAnnotation = ImageUpdaterAnnotationPrefix + "/%s.tag-match"
+ IgnoreTagsOptionAnnotation = ImageUpdaterAnnotationPrefix + "/%s.ignore-tags"
+ UpdateStrategyAnnotation = ImageUpdaterAnnotationPrefix + "/%s.update-strategy"
)
// Image pull secret related annotations
diff --git a/pkg/image/options.go b/pkg/image/options.go
index ea0515e..f777cf0 100644
--- a/pkg/image/options.go
+++ b/pkg/image/options.go
@@ -114,6 +114,7 @@ func (img *ContainerImage) GetParameterMatch(annotations map[string]string) (Mat
}
}
+// GetParameterPullSecret retrieves an image's pull secret credentials
func (img *ContainerImage) GetParameterPullSecret(annotations map[string]string) *CredentialSource {
key := fmt.Sprintf(common.SecretListAnnotation, img.normalizedSymbolicName())
val, ok := annotations[key]
@@ -129,6 +130,26 @@ func (img *ContainerImage) GetParameterPullSecret(annotations map[string]string)
return credSrc
}
+// GetParameterIgnoreTags retrieves a list of tags to ignore from a comma-separated string
+func (img *ContainerImage) GetParameterIgnoreTags(annotations map[string]string) []string {
+ key := fmt.Sprintf(common.IgnoreTagsOptionAnnotation, img.normalizedSymbolicName())
+ val, ok := annotations[key]
+ if !ok {
+ log.Tracef("No ignore-tags annotation %s found", key)
+ return nil
+ }
+ ignoreList := make([]string, 0)
+ tags := strings.Split(strings.TrimSpace(val), ",")
+ for _, tag := range tags {
+ // We ignore empty tags
+ trimmed := strings.TrimSpace(tag)
+ if trimmed != "" {
+ ignoreList = append(ignoreList, trimmed)
+ }
+ }
+ return ignoreList
+}
+
func (img *ContainerImage) normalizedSymbolicName() string {
return strings.ReplaceAll(img.ImageAlias, "/", "_")
}
diff --git a/pkg/image/options_test.go b/pkg/image/options_test.go
index 493c59c..182fc02 100644
--- a/pkg/image/options_test.go
+++ b/pkg/image/options_test.go
@@ -178,3 +178,18 @@ func Test_GetSecretOption(t *testing.T) {
require.Nil(t, credSrc)
})
}
+
+func Test_GetIgnoreTags(t *testing.T) {
+ t.Run("Get list of tags to ignore from annotation", func(t *testing.T) {
+ annotations := map[string]string{
+ fmt.Sprintf(common.IgnoreTagsOptionAnnotation, "dummy"): "tag1, ,tag2, tag3 , tag4",
+ }
+ img := NewFromIdentifier("dummy=foo/bar:1.12")
+ tags := img.GetParameterIgnoreTags(annotations)
+ require.Len(t, tags, 4)
+ assert.Equal(t, "tag1", tags[0])
+ assert.Equal(t, "tag2", tags[1])
+ assert.Equal(t, "tag3", tags[2])
+ assert.Equal(t, "tag4", tags[3])
+ })
+}
diff --git a/pkg/image/version.go b/pkg/image/version.go
index 392d127..3abdc7d 100644
--- a/pkg/image/version.go
+++ b/pkg/image/version.go
@@ -1,6 +1,8 @@
package image
import (
+ "path/filepath"
+
"github.com/argoproj-labs/argocd-image-updater/pkg/log"
"github.com/argoproj-labs/argocd-image-updater/pkg/tag"
@@ -36,6 +38,7 @@ type VersionConstraint struct {
Constraint string
MatchFunc MatchFuncFn
MatchArgs interface{}
+ IgnoreList []string
SortMode VersionSortMode
}
@@ -123,3 +126,14 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
return img.ImageTag, nil
}
}
+
+// IsTagIgnored matches tag against the patterns in IgnoreList and returns true if one of them matches
+func (vc *VersionConstraint) IsTagIgnored(tag string) bool {
+ for _, t := range vc.IgnoreList {
+ if match, err := filepath.Match(t, tag); err == nil && match {
+ log.Tracef("tag %s is ignored by pattern %s", tag, t)
+ return true
+ }
+ }
+ return false
+}
diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go
index ffe895d..496e301 100644
--- a/pkg/registry/registry.go
+++ b/pkg/registry/registry.go
@@ -42,8 +42,8 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
// Loop through tags, removing those we do not want
if vc.MatchFunc != nil {
for _, t := range tTags {
- if !vc.MatchFunc(t, vc.MatchArgs) {
- log.Tracef("Removing tag %s because of tag match options", t)
+ if !vc.MatchFunc(t, vc.MatchArgs) || vc.IsTagIgnored(t) {
+ log.Tracef("Removing tag %s because it either didn't match defined pattern or is ignored", t)
} else {
tags = append(tags, t)
}