Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: rename VersionSortMode to UpdateStrategy #343

Merged
merged 1 commit into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ argocd-image-updater test nginx --allow-tags '^1.19.\d+(\-.*)*$' --update-strate

vc := &image.VersionConstraint{
Constraint: semverConstraint,
SortMode: image.VersionSortSemVer,
Strategy: image.StrategySemVer,
}

vc.SortMode = image.ParseUpdateStrategy(strategy)
vc.Strategy = image.ParseUpdateStrategy(strategy)

if allowTags != "" {
vc.MatchFunc, vc.MatchArgs = image.ParseMatchfunc(allowTags)
Expand All @@ -101,7 +101,7 @@ argocd-image-updater test nginx --allow-tags '^1.19.\d+(\-.*)*$' --update-strate
}
vc.Options = vc.Options.
WithPlatform(os, arch, variant).
WithMetadata(vc.SortMode.NeedsMetadata())
WithMetadata(vc.Strategy.NeedsMetadata())
}

if registriesConfPath != "" {
Expand Down
6 changes: 3 additions & 3 deletions pkg/argocd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,10 @@ func UpdateApplication(updateConf *UpdateConfiguration, state *SyncIterationStat
imgCtx.Debugf("Using no version constraint when looking for a new tag")
}

vc.SortMode = applicationImage.GetParameterUpdateStrategy(updateConf.UpdateApp.Application.Annotations)
vc.Strategy = applicationImage.GetParameterUpdateStrategy(updateConf.UpdateApp.Application.Annotations)
vc.MatchFunc, vc.MatchArgs = applicationImage.GetParameterMatch(updateConf.UpdateApp.Application.Annotations)
vc.IgnoreList = applicationImage.GetParameterIgnoreTags(updateConf.UpdateApp.Application.Annotations)
vc.Options = applicationImage.GetPlatformOptions(updateConf.UpdateApp.Application.Annotations, updateConf.IgnorePlatforms).WithMetadata(vc.SortMode.NeedsMetadata())
vc.Options = applicationImage.GetPlatformOptions(updateConf.UpdateApp.Application.Annotations, updateConf.IgnorePlatforms).WithMetadata(vc.Strategy.NeedsMetadata())

// The endpoint can provide default credentials for pulling images
err = rep.SetEndpointCredentials(updateConf.KubeClient)
Expand Down Expand Up @@ -257,7 +257,7 @@ func UpdateApplication(updateConf *UpdateConfiguration, state *SyncIterationStat
// image is configured to use a tag and no digest, we need to set an
// initial dummy digest, so that tag.Equals() will return false.
// TODO: Fix this. This is just a workaround.
if vc.SortMode == image.VersionSortDigest {
if vc.Strategy == image.StrategyDigest {
if !updateableImage.ImageTag.IsDigest() {
log.Tracef("Setting dummy digest for image %s", updateableImage.GetFullNameWithTag())
updateableImage.ImageTag.TagDigest = "dummy"
Expand Down
16 changes: 8 additions & 8 deletions pkg/image/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,31 +65,31 @@ func (img *ContainerImage) HasForceUpdateOptionAnnotation(annotations map[string

// GetParameterSort gets and validates the value for the sort option for the
// image from a set of annotations
func (img *ContainerImage) GetParameterUpdateStrategy(annotations map[string]string) VersionSortMode {
func (img *ContainerImage) GetParameterUpdateStrategy(annotations map[string]string) UpdateStrategy {
key := fmt.Sprintf(common.UpdateStrategyAnnotation, img.normalizedSymbolicName())
val, ok := annotations[key]
if !ok {
// Default is sort by version
log.Tracef("No sort option %s found", key)
return VersionSortSemVer
return StrategySemVer
}
log.Tracef("found update strategy %s in %s", val, key)
return ParseUpdateStrategy(val)
}

func ParseUpdateStrategy(val string) VersionSortMode {
func ParseUpdateStrategy(val string) UpdateStrategy {
switch strings.ToLower(val) {
case "semver":
return VersionSortSemVer
return StrategySemVer
case "latest":
return VersionSortLatest
return StrategyLatest
case "name":
return VersionSortName
return StrategyName
case "digest":
return VersionSortDigest
return StrategyDigest
default:
log.Warnf("Unknown sort option %s -- using semver", val)
return VersionSortSemVer
return StrategySemVer
}

}
Expand Down
10 changes: 5 additions & 5 deletions pkg/image/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func Test_GetSortOption(t *testing.T) {
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, VersionSortSemVer, sortMode)
assert.Equal(t, StrategySemVer, sortMode)
})

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

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

t.Run("Get update strategy option configured application because of invalid option", func(t *testing.T) {
Expand All @@ -110,14 +110,14 @@ func Test_GetSortOption(t *testing.T) {
}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, VersionSortSemVer, sortMode)
assert.Equal(t, StrategySemVer, sortMode)
})

t.Run("Get update strategy option configured application because of option not set", func(t *testing.T) {
annotations := map[string]string{}
img := NewFromIdentifier("dummy=foo/bar:1.12")
sortMode := img.GetParameterUpdateStrategy(annotations)
assert.Equal(t, VersionSortSemVer, sortMode)
assert.Equal(t, StrategySemVer, sortMode)
})
}

Expand Down
66 changes: 43 additions & 23 deletions pkg/image/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ import (
)

// VersionSortMode defines the method to sort a list of tags
type VersionSortMode int
type UpdateStrategy int

const (
// VersionSortSemVer sorts tags using semver sorting (the default)
VersionSortSemVer VersionSortMode = 0
StrategySemVer UpdateStrategy = 0
// VersionSortLatest sorts tags after their creation date
VersionSortLatest VersionSortMode = 1
StrategyLatest UpdateStrategy = 1
// VersionSortName sorts tags alphabetically by name
VersionSortName VersionSortMode = 2
StrategyName UpdateStrategy = 2
// VersionSortDigest uses latest digest of an image
VersionSortDigest VersionSortMode = 3
StrategyDigest UpdateStrategy = 3
)

// ConstraintMatchMode defines how the constraint should be matched
Expand All @@ -42,7 +42,7 @@ type VersionConstraint struct {
MatchFunc MatchFuncFn
MatchArgs interface{}
IgnoreList []string
SortMode VersionSortMode
Strategy UpdateStrategy
Options *options.ManifestOptions
}

Expand All @@ -61,14 +61,14 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
logCtx.AddField("image", img.String())

var availableTags tag.SortableImageTagList
switch vc.SortMode {
case VersionSortSemVer:
switch vc.Strategy {
case StrategySemVer:
availableTags = tagList.SortBySemVer()
case VersionSortName:
case StrategyName:
availableTags = tagList.SortByName()
case VersionSortLatest:
case StrategyLatest:
availableTags = tagList.SortByDate()
case VersionSortDigest:
case StrategyDigest:
availableTags = tagList.SortByName()
}

Expand All @@ -82,7 +82,7 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
// The given constraint MUST match a semver constraint
var semverConstraint *semver.Constraints
var err error
if vc.SortMode == VersionSortSemVer {
if vc.Strategy == StrategySemVer {
// TODO: Shall we really ensure a valid semver on the current tag?
// This prevents updating from a non-semver tag currently.
if img.ImageTag != nil && img.ImageTag.TagName != "" {
Expand All @@ -93,7 +93,7 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
}

if vc.Constraint != "" {
if vc.SortMode == VersionSortSemVer {
if vc.Strategy == StrategySemVer {
semverConstraint, err = semver.NewConstraint(vc.Constraint)
if err != nil {
logCtx.Errorf("invalid constraint '%s' given: '%v'", vc, err)
Expand All @@ -107,7 +107,7 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
for _, tag := range availableTags {
logCtx.Tracef("Finding out whether to consider %s for being updateable", tag.TagName)

if vc.SortMode == VersionSortSemVer {
if vc.Strategy == StrategySemVer {
// Non-parseable tag does not mean error - just skip it
ver, err := semver.NewVersion(tag.TagName)
if err != nil {
Expand All @@ -123,7 +123,7 @@ func (img *ContainerImage) GetNewestVersionFromTags(vc *VersionConstraint, tagLi
continue
}
}
} else if vc.SortMode == VersionSortDigest {
} else if vc.Strategy == StrategyDigest {
if tag.TagName != vc.Constraint {
logCtx.Tracef("%s did not match contraint %s", tag.TagName, vc.Constraint)
continue
Expand Down Expand Up @@ -156,20 +156,40 @@ func (vc *VersionConstraint) IsTagIgnored(tag string) bool {
return false
}

// IsCacheable returns true if we can safely cache tags for a given sort mode
func (vsm VersionSortMode) IsCacheable() bool {
switch vsm {
case VersionSortDigest:
// IsCacheable returns true if we can safely cache tags for strategy s
func (s UpdateStrategy) IsCacheable() bool {
switch s {
case StrategyDigest:
return false
default:
return true
}
}

// NeedsMetadata returns true if v requires image metadata to work correctly
func (vsm VersionSortMode) NeedsMetadata() bool {
switch vsm {
case VersionSortLatest:
// NeedsMetadata returns true if strategy s requires image metadata to work correctly
func (s UpdateStrategy) NeedsMetadata() bool {
switch s {
case StrategyLatest:
return true
default:
return false
}
}

// NeedsVersionConstraint returns true if strategy s requires a version constraint to be defined
func (s UpdateStrategy) NeedsVersionConstraint() bool {
switch s {
case StrategyDigest:
return true
default:
return false
}
}

// WantsOnlyConstraintTag returns true if strategy s only wants to inspect the tag specified by the constraint
func (s UpdateStrategy) WantsOnlyConstraintTag() bool {
switch s {
case StrategyDigest:
return true
default:
return false
Expand Down
4 changes: 2 additions & 2 deletions 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{SortMode: VersionSortLatest}
vc := VersionConstraint{Strategy: StrategyLatest}
newTag, err := img.GetNewestVersionFromTags(&vc, tagList)
require.NoError(t, err)
require.NotNil(t, newTag)
Expand All @@ -98,7 +98,7 @@ func Test_LatestVersion(t *testing.T) {
t.Run("Find the latest version using latest sortmode, invalid tags", func(t *testing.T) {
tagList := newImageTagListWithDate([]string{"zz", "bb", "yy", "cc", "yy", "aa", "ll"})
img := NewFromIdentifier("jannfis/test:bb")
vc := VersionConstraint{SortMode: VersionSortSemVer}
vc := VersionConstraint{Strategy: StrategySemVer}
newTag, err := img.GetNewestVersionFromTags(&vc, tagList)
require.NoError(t, err)
require.NotNil(t, newTag)
Expand Down
14 changes: 7 additions & 7 deletions pkg/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
tags := []string{}

// For digest strategy, we do require a version constraint
if vc.SortMode == image.VersionSortDigest && vc.Constraint == "" {
return nil, fmt.Errorf("cannot use digest strategy for image %s without a version constraint", img.Original())
if vc.Strategy.NeedsVersionConstraint() && vc.Constraint == "" {
return nil, fmt.Errorf("cannot use update strategy 'digest' for image '%s' without a version constraint", img.Original())
}

// Loop through tags, removing those we do not want. If update strategy is
// digest, all but the constraint tag are ignored.
if vc.MatchFunc != nil || len(vc.IgnoreList) > 0 || vc.SortMode == image.VersionSortDigest {
if vc.MatchFunc != nil || len(vc.IgnoreList) > 0 || vc.Strategy.WantsOnlyConstraintTag() {
for _, t := range tTags {
if (vc.MatchFunc != nil && !vc.MatchFunc(t, vc.MatchArgs)) || vc.IsTagIgnored(t) || (vc.SortMode == image.VersionSortDigest && t != vc.Constraint) {
if (vc.MatchFunc != nil && !vc.MatchFunc(t, vc.MatchArgs)) || vc.IsTagIgnored(t) || (vc.Strategy.WantsOnlyConstraintTag() && t != vc.Constraint) {
log.Tracef("Removing tag %s because it either didn't match defined pattern or is ignored", t)
} else {
tags = append(tags, t)
Expand All @@ -78,7 +78,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.SortMode != image.VersionSortLatest && vc.SortMode != image.VersionSortDigest) || endpoint.TagListSort.IsTimeSorted() {
if (vc.Strategy != image.StrategyLatest && vc.Strategy != image.StrategyDigest) || endpoint.TagListSort.IsTimeSorted() {
for i, tagStr := range tags {
var ts int
if endpoint.TagListSort == SortLatestFirst {
Expand Down Expand Up @@ -106,7 +106,7 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
// Look into the cache first and re-use any found item. If GetTag() returns
// an error, we treat it as a cache miss and just go ahead to invalidate
// the entry.
if vc.SortMode.IsCacheable() {
if vc.Strategy.IsCacheable() {
imgTag, err := endpoint.Cache.GetTag(nameInRegistry, tagStr)
if err != nil {
log.Warnf("invalid entry for %s:%s in cache, invalidating.", nameInRegistry, imgTag.TagName)
Expand Down Expand Up @@ -161,7 +161,7 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R

log.Tracef("Found date %s", ti.CreatedAt.String())
var imgTag *tag.ImageTag
if vc.SortMode == image.VersionSortDigest {
if vc.Strategy == image.StrategyDigest {
imgTag = tag.NewImageTag(tagStr, ti.CreatedAt, fmt.Sprintf("sha256:%x", ti.Digest))
} else {
imgTag = tag.NewImageTag(tagStr, ti.CreatedAt, "")
Expand Down
8 changes: 4 additions & 4 deletions pkg/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Test_GetTags(t *testing.T) {

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

tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortSemVer})
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategySemVer})
require.NoError(t, err)
assert.NotEmpty(t, tl)

Expand All @@ -46,7 +46,7 @@ func Test_GetTags(t *testing.T) {

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

tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortSemVer, MatchFunc: image.MatchFuncNone})
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategySemVer, MatchFunc: image.MatchFuncNone})
require.NoError(t, err)
assert.Empty(t, tl.Tags())

Expand All @@ -66,7 +66,7 @@ func Test_GetTags(t *testing.T) {

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

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

Expand Down Expand Up @@ -98,7 +98,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{SortMode: image.VersionSortLatest})
tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{Strategy: image.StrategyLatest})
require.NoError(t, err)
assert.NotEmpty(t, tl)

Expand Down