Skip to content
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ enrich version checking on image tags:
is. In this example, the current version of `my-container` will be compared
against the image versions in the `docker.io/bitnami/etcd` registry.

- `resolve-sha-to-tags.version-checker.io/my-container`: is used to
resolve images specified using sha256 in kubernetes manifests to valid semver
tags. To enable this the annotation value must be set to "true".

## Known configurations

From time to time, version-checker may need some of the above options applied to determine the latest version,
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ github.com/Azure/go-autorest/logger v0.2.2/go.mod h1:I5fg9K52o+iuydlWfa9T5K6WFos
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/Azure/go-autorest/tracing v0.6.1 h1:YUMSrC/CeD1ZnnXcNYU4a/fzsO35u2Fsful9L/2nyR0=
github.com/Azure/go-autorest/tracing v0.6.1/go.mod h1:/3EgjbsjraOqiicERAeu3m7/z0x1TzjQGAwDrJrXGkc=
github.com/MicahParks/jwkset v0.5.19 h1:XZCsgJv05DBCvxEHYEHlSafqiuVn5ESG0VRB331Fxhw=
github.com/MicahParks/jwkset v0.5.19/go.mod h1:q8ptTGn/Z9c4MwbcfeCDssADeVQb3Pk7PnVxrvi+2QY=
github.com/MicahParks/jwkset v0.8.0 h1:jHtclI38Gibmu17XMI6+6/UB59srp58pQVxePHRK5o8=
github.com/MicahParks/jwkset v0.8.0/go.mod h1:fVrj6TmG1aKlJEeceAz7JsXGTXEn72zP1px3us53JrA=
github.com/MicahParks/keyfunc/v3 v3.3.5 h1:7ceAJLUAldnoueHDNzF8Bx06oVcQ5CfJnYwNt1U3YYo=
github.com/MicahParks/keyfunc/v3 v3.3.5/go.mod h1:SdCCyMJn/bYqWDvARspC6nCT8Sk74MjuAY22C7dCST8=
github.com/MicahParks/keyfunc/v3 v3.3.10 h1:JtEGE8OcNeI297AMrR4gVXivV8fyAawFUMkbwNreJRk=
github.com/MicahParks/keyfunc/v3 v3.3.10/go.mod h1:1TEt+Q3FO7Yz2zWeYO//fMxZMOiar808NqjWQQpBPtU=
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
Expand Down
3 changes: 3 additions & 0 deletions pkg/api/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const (
// as its tag.
UseSHAAnnotationKey = "use-sha.version-checker.io"

//ResolveSHAToTagsKey is used to resolve image sha256 to corresponding tags
ResolveSHAToTagsKey = "resolve-sha-to-tags.version-checker.io"

// MatchRegexAnnotationKey will enforce that tags that are looked up must
// match this regex. UseMetaDataAnnotationKey is not required when this is
// set. All other options are ignored when this is set.
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type Options struct {

// UseSHA cannot be used with any other options
UseSHA bool `json:"use-sha,omitempty"`
// Resolve SHA to a TAG
ResolveSHAToTags bool `json:"resolve-sha-to-tags,omitempty"`

MatchRegex *string `json:"match-regex,omitempty"`

Expand Down
16 changes: 16 additions & 0 deletions pkg/controller/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ func (c *Checker) Container(ctx context.Context, log *logrus.Entry,
imageURL, currentTag, currentSHA := urlTagSHAFromImage(container.Image)
usingSHA, usingTag := len(currentSHA) > 0, len(currentTag) > 0

if opts.ResolveSHAToTags {

if len(*opts.OverrideURL) > 0 {
imageURL = *opts.OverrideURL
}
resolvedTag, err := c.search.ResolveSHAToTag(ctx, imageURL, currentSHA)

if len(resolvedTag) > 0 && err == nil {
log.Infof("Successfully resolved tag for sha256: %s at url: %s", currentSHA, imageURL)
currentTag = resolvedTag
usingSHA = false
usingTag = true
}
}

// If using latest or no tag, then compare on SHA
if c.isLatestOrEmptyTag(currentTag) {
c.handleLatestOrEmptyTag(log, currentTag, currentSHA, opts)
usingTag = false
Expand Down
9 changes: 8 additions & 1 deletion pkg/controller/internal/fake/search/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ import (
var _ search.Searcher = &FakeSearch{}

type FakeSearch struct {
latestImageF func() (*api.ImageTag, error)
latestImageF func() (*api.ImageTag, error)
resolveSHAToTagF func() (string, error)
}

func New() *FakeSearch {
return &FakeSearch{
latestImageF: func() (*api.ImageTag, error) {
return nil, nil
},
resolveSHAToTagF: func() (string, error) {
return "", nil
},
}
}

Expand All @@ -33,5 +37,8 @@ func (f *FakeSearch) LatestImage(context.Context, string, *api.Options) (*api.Im
return f.latestImageF()
}

func (f *FakeSearch) ResolveSHAToTag(ctx context.Context, imageURL string, imageSHA string) (string, error) {
return f.resolveSHAToTagF()
}
func (f *FakeSearch) Run(time.Duration) {
}
11 changes: 10 additions & 1 deletion pkg/controller/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func (b *Builder) Options(name string) (*api.Options, error) {
// Define the handlers
handlers := []optionsHandler{
b.handleSHAOption,
b.handleSHAToTagOption,
b.handleMetadataOption,
b.handleRegexOption,
b.handlePinMajorOption,
Expand All @@ -53,7 +54,9 @@ func (b *Builder) Options(name string) (*api.Options, error) {

// Ensure UseSHA is not used with other semver options
if opts.UseSHA && setNonSha {
errs = append(errs, fmt.Sprintf("cannot define %q with any semver options", b.index(name, api.UseSHAAnnotationKey)))
errs = append(errs,
fmt.Sprintf("cannot define %q with any semver options", b.index(name, api.UseSHAAnnotationKey)),
)
}

if len(errs) > 0 {
Expand All @@ -68,6 +71,12 @@ func (b *Builder) handleSHAOption(name string, opts *api.Options, setNonSha *boo
}
return nil
}
func (b *Builder) handleSHAToTagOption(name string, opts *api.Options, setNonSha *bool, errs *[]string) error {
if ResolveSHAToTags, ok := b.ans[b.index(name, api.ResolveSHAToTagsKey)]; ok && ResolveSHAToTags == "true" {
opts.ResolveSHAToTags = true
}
return nil
}

func (b *Builder) handleMetadataOption(name string, opts *api.Options, setNonSha *bool, errs *[]string) error {
if useMetaData, ok := b.ans[b.index(name, api.UseMetaDataAnnotationKey)]; ok && useMetaData == "true" {
Expand Down
10 changes: 10 additions & 0 deletions pkg/controller/options/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ func TestBuild(t *testing.T) {
},
expErr: "",
},
"output options for resolve sha": {
containerName: "test-name",
annotations: map[string]string{
api.ResolveSHAToTagsKey + "/test-name": "true",
},
expOptions: &api.Options{
ResolveSHAToTags: true,
},
expErr: "",
},
"bool options that don't have 'true' and nothing": {
containerName: "test-name",
annotations: map[string]string{
Expand Down
11 changes: 11 additions & 0 deletions pkg/controller/search/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
// Searcher is the interface for Search to facilitate testing.
type Searcher interface {
LatestImage(context.Context, string, *api.Options) (*api.ImageTag, error)
ResolveSHAToTag(ctx context.Context, imageURL string, imageSHA string) (string, error)
}

// Search is the implementation for the searching and caching of image URLs.
Expand Down Expand Up @@ -65,6 +66,16 @@ func (s *Search) LatestImage(ctx context.Context, imageURL string, opts *api.Opt
return lastestImage.(*api.ImageTag), nil
}

func (s *Search) ResolveSHAToTag(ctx context.Context, imageURL string, imageSHA string) (string, error) {

tag, err := s.versionGetter.ResolveSHAToTag(ctx, imageURL, imageSHA)
if err != nil {
return "", fmt.Errorf("failed to resolve sha to tag: %w", err)
}

return tag, err
}

// calculateHashIndex returns a hash index given an imageURL and options.
func calculateHashIndex(imageURL string, opts *api.Options) (string, error) {
optsJSON, err := json.Marshal(opts)
Expand Down
18 changes: 18 additions & 0 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@ func (v *Version) LatestTagFromImage(ctx context.Context, imageURL string, opts
return tag, err
}

// ResolveSHAToTag Resolve a SHA to a tag if possible
func (v *Version) ResolveSHAToTag(ctx context.Context, imageURL string, imageSHA string) (string, error) {

tagsI, err := v.imageCache.Get(ctx, imageURL, imageURL, nil)
if err != nil {
return "", err
}
tags := tagsI.([]api.ImageTag)

for i := range tags {
if tags[i].SHA == imageSHA {
return tags[i].Tag, nil
}
}

return "", nil
}

// Fetch returns the given image tags for a given image URL.
func (v *Version) Fetch(ctx context.Context, imageURL string, _ *api.Options) (interface{}, error) {
// fetch tags from image URL
Expand Down
Loading