Skip to content

Commit

Permalink
feat: Rename confusing update strategies (#456)
Browse files Browse the repository at this point in the history
* rename strategies

* update docs
  • Loading branch information
jaideepr97 authored Jul 20, 2022
1 parent f12a5ab commit a0cf1e3
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 36 deletions.
Binary file added argocd-image-updater
Binary file not shown.
68 changes: 60 additions & 8 deletions docs/basics/update-strategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ The following update strategies are currently supported:

* [semver](#strategy-semver) - Update to the latest version of an image
considering semantic versioning constraints
* [latest](#strategy-latest) - Update to the most recently built image found in a registry
* [latest/newest-build](#strategy-latest) - Update to the most recently built image found in a registry
* [digest](#strategy-digest) - Update to the latest version of a given version (tag), using the tag's SHA digest
* [name](#strategy-name) - Sorts tags alphabetically and update to the one with the highest cardinality
* [name/alphabetical](#strategy-name) - Sorts tags alphabetically and update to the one with the highest cardinality

!!!warning "Renamed image update strategies
The `latest` strategy has been renamed to `newest-build`, and `name` strategy has been renamed to `alphabetical`.
Please switch to the new convention as support for the old naming convention will be removed in future releases.

Some of the strategies will require additional configuration, or can be tweaked
with additional parameters. Please have a look at the
Expand Down Expand Up @@ -97,30 +101,42 @@ Image Updater will pick the highest version number found in the registry.
Argo CD Image Updater will omit any tags from your registry that do not match
a semantic version when using the `semver` update strategy.

### <a name="strategy-latest"></a>latest - Update to the most recently built image
### <a name="strategy-latest"></a>latest/newest-build - Update to the most recently built image


!!!warning "Renamed image update strategies"
The `latest` strategy has been renamed to `newest-build`.
Please switch to the new convention as support for the old naming convention will be removed in future releases.
Detected usage of `latest` will result in a warning message within the image-updater controller logs.

!!!warning
As of November 2020, Docker Hub has introduced pull limits for accounts on
the free plan and unauthenticated requests. The `latest` update strategy
the free plan and unauthenticated requests. The `latest` or `newest-build` update strategy
will perform manifest pulls for determining the most recently pushed tags,
and these will count into your pull limits. So unless you are not affected
by these pull limits, it is **not recommended** to use the `latest` update
by these pull limits, it is **not recommended** to use the `latest` or `newest-build` update
strategy with images hosted on Docker Hub.

!!!note
If you are using *reproducible builds* for your container images (e.g. if
your build pipeline always sets the creation date of the image to the same
value), the `latest` strategy will not be able to determine which tag to
value), the `latest` or `newest-build` strategy will not be able to determine which tag to
update to.

Strategy name: `latest`
Strategy name: `latest` or `newest-build`

Basic configuration:

```yaml
argocd-image-updater.argoproj.io/image-list: <alias>=some/image
argocd-image-updater.argoproj.io/<alias>.update-strategy: latest
```
or
```yaml
argocd-image-updater.argoproj.io/image-list: <alias>=some/image
argocd-image-updater.argoproj.io/<alias>.update-strategy: newest-build
```
Argo CD Image Updater can update to the image that has the most recent build
date, and is tagged with an arbitrary name (e.g. a Git commit SHA, or even a
Expand All @@ -147,6 +163,14 @@ argocd-image-updater.argoproj.io/myimage.update-strategy: latest
argocd-image-updater.argoproj.io/myimage.allow-tags: regexp:^[0-9a-f]{7}$
```

or

```yaml
argocd-image-updater.argoproj.io/image-list: myimage=some/image
argocd-image-updater.argoproj.io/myimage.update-strategy: newest-build
argocd-image-updater.argoproj.io/myimage.allow-tags: regexp:^[0-9a-f]{7}$
```

would only consider tags that match a given regular expression for update. In
this case, the regular expression matches a 7-digit hexadecimal string that
could represent the short version of a Git commit SHA, so it would match tags
Expand All @@ -160,6 +184,14 @@ argocd-image-updater.argoproj.io/myimage.update-strategy: latest
argocd-image-updater.argoproj.io/myimage.ignore-tags: latest, master
```

or

```yaml
argocd-image-updater.argoproj.io/image-list: myimage=some/image
argocd-image-updater.argoproj.io/myimage.update-strategy: newest-build
argocd-image-updater.argoproj.io/myimage.ignore-tags: latest, master
```

This would allow for considering all tags found but `latest` and `master`. You
can read more about filtering tags
[here](../../configuration/images/#filtering-tags).
Expand Down Expand Up @@ -206,14 +238,26 @@ argocd-image-updater.argoproj.io/myimage.update-strategy: digest

### <a name="strategy-name"></a>Update according to lexical sort

Strategy name: `name`
!!!warning "Renamed image update strategies"
The `name` strategy has been renamed to `alphabetical`.
Please switch to the new convention as support for the old naming convention will be removed in future releases.
Detected usage of `name` will result in a warning message within the image-updater controller logs.


Strategy name: `name` or `alphabetical`

Basic configuration:

```yaml
argocd-image-updater.argoproj.io/image-list: <alias>=some/image
argocd-image-updater.argoproj.io/<alias>.update-strategy: name
```
or

```yaml
argocd-image-updater.argoproj.io/image-list: <alias>=some/image
argocd-image-updater.argoproj.io/<alias>.update-strategy: alphabetical
```

This update strategy sorts the tags returned by the registry in a lexical way
(by name, in descending order) and picks the last tag in the list for update.
Expand All @@ -231,6 +275,14 @@ argocd-image-updater.argoproj.io/myimage.update-strategy: name
argocd-image-updater.argoproj.io/myimage.allow-tags: regexp:^[0-9]{4}-[0-9]{2}[0-9]{2}$
```

or

```yaml
argocd-image-updater.argoproj.io/image-list: myimage=some/image
argocd-image-updater.argoproj.io/myimage.update-strategy: alphabetical
argocd-image-updater.argoproj.io/myimage.allow-tags: regexp:^[0-9]{4}-[0-9]{2}[0-9]{2}$
```

would only consider tags that match a given regular expression for update. In
this case, only tags matching a date specification of `YYYY-MM-DD` would be
considered for update.
8 changes: 6 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,18 @@ RBAC authorization on Application resources etc. are fully supported.

## Features

!!!warning "Renamed image update strategies"
The `latest` strategy has been renamed to `newest-build`, and `name` strategy has been renamed to `alphabetical`.
Please switch to the new convention as support for the old naming convention will be removed in future releases.

* Updates images of apps that are managed by Argo CD and are either generated
from *Helm* or *Kustomize* tooling
* Update app images according to different
[update strategies](./basics/update-strategies.md)
* `semver`: update to highest allowed version according to given image
constraint,
* `latest`: update to the most recently created image tag,
* `name`: update to the last tag in an alphabetically sorted list
* `latest/newest-build`: update to the most recently created image tag,
* `name/alphabetical`: update to the last tag in an alphabetically sorted list
* `digest`: update to the most recent pushed version of a mutable tag
* Support for
[widely used container registries](./configuration/registries.md#supported-registries)
Expand Down
10 changes: 8 additions & 2 deletions pkg/image/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,15 @@ func (img *ContainerImage) ParseUpdateStrategy(val string) UpdateStrategy {
case "semver":
return StrategySemVer
case "latest":
return StrategyLatest
logCtx.Warnf("\"latest\" strategy has been renamed to \"newest-build\". Please switch to the new convention as support for the old naming convention will be removed in future versions.")
fallthrough
case "newest-build":
return StrategyNewestBuild
case "name":
return StrategyName
logCtx.Warnf("\"name\" strategy has been renamed to \"alphabetical\". Please switch to the new convention as support for the old naming convention will be removed in future versions.")
fallthrough
case "alphabetical":
return StrategyAlphabetical
case "digest":
return StrategyDigest
default:
Expand Down
32 changes: 25 additions & 7 deletions pkg/image/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,22 @@ func Test_GetSortOption(t *testing.T) {
assert.Equal(t, StrategySemVer, sortMode)
})

t.Run("Use update strategy newest-build for configured application", func(t *testing.T) {
annotations := map[string]string{
fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "newest-build",
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyNewestBuild, sortMode)
})

t.Run("Get update strategy date for configured application", func(t *testing.T) {
annotations := map[string]string{
fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "latest",
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyLatest, sortMode)
assert.Equal(t, StrategyNewestBuild, sortMode)
})

t.Run("Get update strategy name for configured application", func(t *testing.T) {
Expand All @@ -100,7 +109,16 @@ func Test_GetSortOption(t *testing.T) {
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyName, sortMode)
assert.Equal(t, StrategyAlphabetical, sortMode)
})

t.Run("Use update strategy alphabetical for configured application", func(t *testing.T) {
annotations := map[string]string{
fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "alphabetical",
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyAlphabetical, sortMode)
})

t.Run("Get update strategy option configured application because of invalid option", func(t *testing.T) {
Expand All @@ -121,21 +139,21 @@ func Test_GetSortOption(t *testing.T) {

t.Run("Prefer update strategy option from image-specific annotation", func(t *testing.T) {
annotations := map[string]string{
fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "name",
common.ApplicationWideUpdateStrategyAnnotation: "latest",
fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "alphabetical",
common.ApplicationWideUpdateStrategyAnnotation: "newest-build",
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyName, sortMode)
assert.Equal(t, StrategyAlphabetical, sortMode)
})

t.Run("Get update strategy option from application-wide annotation", func(t *testing.T) {
annotations := map[string]string{
common.ApplicationWideUpdateStrategyAnnotation: "latest",
common.ApplicationWideUpdateStrategyAnnotation: "newest-build",
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, StrategyLatest, sortMode)
assert.Equal(t, StrategyNewestBuild, sortMode)
})
}

Expand Down
22 changes: 11 additions & 11 deletions pkg/image/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const (
// VersionSortSemVer sorts tags using semver sorting (the default)
StrategySemVer UpdateStrategy = 0
// VersionSortLatest sorts tags after their creation date
StrategyLatest UpdateStrategy = 1
StrategyNewestBuild UpdateStrategy = 1
// VersionSortName sorts tags alphabetically by name
StrategyName UpdateStrategy = 2
StrategyAlphabetical UpdateStrategy = 2
// VersionSortDigest uses latest digest of an image
StrategyDigest UpdateStrategy = 3
)
Expand All @@ -28,10 +28,10 @@ func (us UpdateStrategy) String() string {
switch us {
case StrategySemVer:
return "semver"
case StrategyLatest:
return "latest"
case StrategyName:
return "name"
case StrategyNewestBuild:
return "newest-build"
case StrategyAlphabetical:
return "alphabetical"
case StrategyDigest:
return "digest"
}
Expand Down Expand Up @@ -87,12 +87,12 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
switch vc.Strategy {
case StrategySemVer:
availableTags = tagList.SortBySemVer()
case StrategyName:
availableTags = tagList.SortByName()
case StrategyLatest:
case StrategyAlphabetical:
availableTags = tagList.SortAlphabetically()
case StrategyNewestBuild:
availableTags = tagList.SortByDate()
case StrategyDigest:
availableTags = tagList.SortByName()
availableTags = tagList.SortAlphabetically()
}

considerTags := tag.SortableImageTagList{}
Expand Down Expand Up @@ -192,7 +192,7 @@ func (s UpdateStrategy) IsCacheable() bool {
// NeedsMetadata returns true if strategy s requires image metadata to work correctly
func (s UpdateStrategy) NeedsMetadata() bool {
switch s {
case StrategyLatest:
case StrategyNewestBuild:
return true
default:
return false
Expand Down
2 changes: 1 addition & 1 deletion pkg/image/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func Test_LatestVersion(t *testing.T) {
t.Run("Find the latest version using latest sortmode", func(t *testing.T) {
tagList := newImageTagListWithDate([]string{"zz", "bb", "yy", "cc", "yy", "aa", "ll"})
img := NewFromIdentifier("jannfis/test:bb")
vc := VersionConstraint{Strategy: StrategyLatest}
vc := VersionConstraint{Strategy: StrategyNewestBuild}
newTag, err := img.GetNewestVersionFromTags(&vc, tagList)
require.NoError(t, err)
require.NotNil(t, newTag)
Expand Down
2 changes: 1 addition & 1 deletion pkg/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
//
// We just create a dummy time stamp according to the registry's sort mode, if
// set.
if (vc.Strategy != image.StrategyLatest && vc.Strategy != image.StrategyDigest) || endpoint.TagListSort.IsTimeSorted() {
if (vc.Strategy != image.StrategyNewestBuild && vc.Strategy != image.StrategyDigest) || endpoint.TagListSort.IsTimeSorted() {
for i, tagStr := range tags {
var ts int
if endpoint.TagListSort == TagListSortLatestFirst {
Expand Down
4 changes: 2 additions & 2 deletions pkg/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func Test_GetTags(t *testing.T) {

img := image.NewFromIdentifier("foo/bar:1.2.0")

tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategyName, Options: options.NewManifestOptions()})
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategyAlphabetical, Options: options.NewManifestOptions()})
require.NoError(t, err)
assert.NotEmpty(t, tl)

Expand Down Expand Up @@ -102,7 +102,7 @@ func Test_GetTags(t *testing.T) {
ep.Cache.ClearCache()

img := image.NewFromIdentifier("foo/bar:1.2.0")
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategyLatest, Options: options.NewManifestOptions()})
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategyNewestBuild, Options: options.NewManifestOptions()})
require.NoError(t, err)
assert.NotEmpty(t, tl)

Expand Down
2 changes: 1 addition & 1 deletion pkg/tag/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (il ImageTagList) Add(tag *ImageTag) {
}

// SortByName returns an array of ImageTag objects, sorted by the tag's name
func (il ImageTagList) SortByName() SortableImageTagList {
func (il ImageTagList) SortAlphabetically() SortableImageTagList {
sil := SortableImageTagList{}
for _, v := range il.items {
sil = append(sil, v)
Expand Down
2 changes: 1 addition & 1 deletion pkg/tag/tag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func Test_SortableImageTagList(t *testing.T) {
tag := NewImageTag(name, time.Now(), "")
il.Add(tag)
}
sil := il.SortByName()
sil := il.SortAlphabetically()
require.Len(t, sil, len(names))
assert.Equal(t, "alpha", sil[0].TagName)
assert.Equal(t, "bazar", sil[1].TagName)
Expand Down

0 comments on commit a0cf1e3

Please sign in to comment.