From 00ed9d24e2fdf33355c7dcdadfe882ca575b0612 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sat, 8 Jun 2019 19:42:19 +0200 Subject: [PATCH] Add option to set the maximum number of tags to watch for an item if watch_repo is enabled --- CHANGELOG.md | 4 ++++ README.md | 3 ++- internal/app/diun.go | 4 ++-- internal/config/config.go | 11 +++++++++++ internal/model/item.go | 1 + pkg/docker/tags.go | 18 ++++++++++++++---- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8426f9a..0a0e5356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.4.0 (2019/06/08) + +* Add option to set the maximum number of tags to watch for an item if `watch_repo` is enabled + ## 0.3.2 (2019/06/08) * Fix registry client context diff --git a/README.md b/README.md index 0647945a..a26dbb44 100644 --- a/README.md +++ b/README.md @@ -160,9 +160,10 @@ items: * `timeout`: Timeout is the maximum amount of time for the TCP connection to establish. 0 means no timeout (default: `10`). * `insecure_tls`: Allow contacting docker registry over HTTP, or HTTPS with failed TLS verification (default: `false`). * `items`: Slice of items to watch with the following fields: - * `image`: Docker image to watch using `registry/path:tag` format. If registry is omitted, `docker.io` will be used. If tag is omitted, `latest` will be used. **required** + * `image`: Docker image to watch using `registry/path:tag` format. If registry is omitted, `docker.io` will be used and if tag is omitted, `latest` will be used. **required** * `registry_id`: Registry ID from `registries` to use. * `watch_repo`: Watch all tags of this `image` repository (default: `false`). + * `max_tags`: Maximum number of tags to watch if `watch_repo` enabled. 0 means all of them (default: `25`). * `include_tags`: List of regular expressions to include tags. Can be useful if you enable `watch_repo`. * `exclude_tags`: List of regular expressions to exclude tags. Can be useful if you enable `watch_repo`. diff --git a/internal/app/diun.go b/internal/app/diun.go index 46872cee..929f556f 100644 --- a/internal/app/diun.go +++ b/internal/app/diun.go @@ -135,12 +135,12 @@ func (di *Diun) analyzeImage(imageStr string, item model.Item, reg *docker.Regis } func (di *Diun) analyzeRepo(image registry.Image, item model.Item, reg *docker.RegistryClient) { - tags, err := reg.Tags(image) + tags, tagsCount, err := reg.Tags(image, item.MaxTags) if err != nil { log.Error().Err(err).Str("image", image.String()).Msg("Cannot retrieve tags") return } - log.Debug().Str("image", image.String()).Msgf("%d tag(s) found in repository", len(tags)) + log.Debug().Str("image", image.String()).Msgf("%d tag(s) found in repository. %d will be analyzed.", tagsCount, len(tags)) for _, tag := range tags { imageStr := fmt.Sprintf("%s/%s:%s", image.Domain, image.Path, tag) diff --git a/internal/config/config.go b/internal/config/config.go index 16707cc3..7e2d0aa9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -102,6 +102,17 @@ func (cfg *Config) Check() error { } for key, item := range cfg.Items { + if item.Image == "" { + return fmt.Errorf("image is required for item %d", key) + } + + if err := mergo.Merge(&item, model.Item{ + WatchRepo: false, + MaxTags: 25, + }); err != nil { + return fmt.Errorf("cannot set default item values for %s: %v", item.Image, err) + } + if item.RegistryID != "" { reg, found := cfg.Registries[item.RegistryID] if !found { diff --git a/internal/model/item.go b/internal/model/item.go index f99b6b44..c3a0cc3c 100644 --- a/internal/model/item.go +++ b/internal/model/item.go @@ -5,6 +5,7 @@ type Item struct { Image string `yaml:"image,omitempty" json:",omitempty"` RegistryID string `yaml:"registry_id,omitempty" json:",omitempty"` WatchRepo bool `yaml:"watch_repo,omitempty" json:",omitempty"` + MaxTags int `yaml:"max_tags,omitempty" json:",omitempty"` IncludeTags []string `yaml:"include_tags,omitempty" json:",omitempty"` ExcludeTags []string `yaml:"exclude_tags,omitempty" json:",omitempty"` Registry Registry `yaml:"-" json:"-"` diff --git a/pkg/docker/tags.go b/pkg/docker/tags.go index 188717d9..c6206f18 100644 --- a/pkg/docker/tags.go +++ b/pkg/docker/tags.go @@ -8,20 +8,30 @@ import ( type Tags []string // Tags returns tags of a Docker repository -func (c *RegistryClient) Tags(image registry.Image) (Tags, error) { +func (c *RegistryClient) Tags(image registry.Image, max int) (Tags, int, error) { ctx, cancel := c.timeoutContext() defer cancel() imgCls, err := c.newImage(ctx, image.String()) if err != nil { - return nil, err + return nil, 0, err } defer imgCls.Close() tags, err := docker.GetRepositoryTags(ctx, c.sysCtx, imgCls.Reference()) if err != nil { - return nil, err + return nil, 0, err } - return Tags(tags), err + // Reverse order (latest tags first) + for i := len(tags)/2 - 1; i >= 0; i-- { + opp := len(tags) - 1 - i + tags[i], tags[opp] = tags[opp], tags[i] + } + + if max > 0 && len(tags) >= max { + return Tags(tags[:max]), len(tags), nil + } + + return Tags(tags), len(tags), nil }