mirror of
https://github.com/crazy-max/diun.git
synced 2025-12-21 21:33:22 +01:00
Filter tags before return them
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## 0.4.1 (2019/06/08)
|
||||
|
||||
* Filter tags before return them
|
||||
|
||||
## 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
|
||||
|
||||
@@ -37,7 +37,7 @@ Choose the archive matching the destination platform and extract diun:
|
||||
|
||||
```
|
||||
$ cd /opt
|
||||
$ wget -qO- https://github.com/crazy-max/diun/releases/download/v0.4.0/diun_0.4.0_linux_x86_64.tar.gz | tar -zxvf - diun
|
||||
$ wget -qO- https://github.com/crazy-max/diun/releases/download/v0.4.1/diun_0.4.1_linux_x86_64.tar.gz | tar -zxvf - diun
|
||||
```
|
||||
|
||||
After getting the binary, it can be tested with `./diun --help` or moved to a permanent location.
|
||||
@@ -141,7 +141,7 @@ items:
|
||||
watch_repo: true
|
||||
max_tags: 10
|
||||
include_tags:
|
||||
- ^(0|[1-9]\d*)\.*
|
||||
- ^(0|[1-9]\d*)\..*
|
||||
```
|
||||
|
||||
* `db`
|
||||
|
||||
@@ -87,10 +87,10 @@ func (di *Diun) analyzeImage(imageStr string, item model.Item, reg *docker.Regis
|
||||
return registry.Image{}, fmt.Errorf("cannot parse image name %s: %v", item.Image, err)
|
||||
}
|
||||
|
||||
if !di.isIncluded(image.Tag, item.IncludeTags) {
|
||||
if !utl.IsIncluded(image.Tag, item.IncludeTags) {
|
||||
log.Warn().Str("image", image.String()).Msgf("Tag %s not included", image.Tag)
|
||||
return image, nil
|
||||
} else if di.isExcluded(image.Tag, item.ExcludeTags) {
|
||||
} else if utl.IsExcluded(image.Tag, item.ExcludeTags) {
|
||||
log.Warn().Str("image", image.String()).Msgf("Tag %s excluded", image.Tag)
|
||||
return image, nil
|
||||
}
|
||||
@@ -135,14 +135,25 @@ 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, tagsCount, err := reg.Tags(image, item.MaxTags)
|
||||
tags, err := reg.Tags(docker.TagsOptions{
|
||||
Image: image,
|
||||
Max: item.MaxTags,
|
||||
Include: item.IncludeTags,
|
||||
Exclude: item.ExcludeTags,
|
||||
})
|
||||
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. %d will be analyzed.", tagsCount, len(tags))
|
||||
log.Debug().Str("image", image.String()).Msgf("%d tag(s) found in repository. %d will be analyzed (%d max, %d not included, %d excluded).",
|
||||
tags.Total,
|
||||
len(tags.List),
|
||||
item.MaxTags,
|
||||
tags.NotIncluded,
|
||||
tags.Excluded,
|
||||
)
|
||||
|
||||
for _, tag := range tags {
|
||||
for _, tag := range tags.List {
|
||||
imageStr := fmt.Sprintf("%s/%s:%s", image.Domain, image.Path, tag)
|
||||
if _, err := di.analyzeImage(imageStr, item, reg); err != nil {
|
||||
log.Error().Err(err).Str("image", imageStr).Msg("Cannot analyze image")
|
||||
@@ -158,30 +169,6 @@ func (di *Diun) Close() {
|
||||
}
|
||||
}
|
||||
|
||||
func (di *Diun) isIncluded(tag string, includes []string) bool {
|
||||
if len(includes) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, include := range includes {
|
||||
if utl.MatchString(include, tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (di *Diun) isExcluded(tag string, excludes []string) bool {
|
||||
if len(excludes) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, exclude := range excludes {
|
||||
if utl.MatchString(exclude, tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (di *Diun) trackTime(start time.Time, prefix string) {
|
||||
log.Info().Msgf("%s%s", prefix, durafmt.ParseShort(time.Since(start)).String())
|
||||
}
|
||||
|
||||
@@ -13,3 +13,31 @@ func MatchString(exp string, s string) bool {
|
||||
}
|
||||
return re.MatchString(s)
|
||||
}
|
||||
|
||||
// IsIncluded checks if s string is included in includes
|
||||
// If includes is empty, assume true
|
||||
func IsIncluded(s string, includes []string) bool {
|
||||
if len(includes) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, include := range includes {
|
||||
if MatchString(include, s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsExcluded checks if s string is excluded in excludes
|
||||
// If excludes is empty, assume false
|
||||
func IsExcluded(s string, excludes []string) bool {
|
||||
if len(excludes) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, exclude := range excludes {
|
||||
if MatchString(exclude, s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -2,36 +2,67 @@ package docker
|
||||
|
||||
import (
|
||||
"github.com/containers/image/docker"
|
||||
"github.com/crazy-max/diun/internal/utl"
|
||||
"github.com/crazy-max/diun/pkg/docker/registry"
|
||||
)
|
||||
|
||||
type Tags []string
|
||||
type Tags struct {
|
||||
List []string
|
||||
NotIncluded int
|
||||
Excluded int
|
||||
Total int
|
||||
}
|
||||
|
||||
type TagsOptions struct {
|
||||
Image registry.Image
|
||||
Max int
|
||||
Include []string
|
||||
Exclude []string
|
||||
}
|
||||
|
||||
// Tags returns tags of a Docker repository
|
||||
func (c *RegistryClient) Tags(image registry.Image, max int) (Tags, int, error) {
|
||||
func (c *RegistryClient) Tags(opts TagsOptions) (*Tags, error) {
|
||||
ctx, cancel := c.timeoutContext()
|
||||
defer cancel()
|
||||
|
||||
imgCls, err := c.newImage(ctx, image.String())
|
||||
imgCls, err := c.newImage(ctx, opts.Image.String())
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
defer imgCls.Close()
|
||||
|
||||
tags, err := docker.GetRepositoryTags(ctx, c.sysCtx, imgCls.Reference())
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &Tags{
|
||||
NotIncluded: 0,
|
||||
Excluded: 0,
|
||||
Total: len(tags),
|
||||
}
|
||||
|
||||
// Filter
|
||||
for _, tag := range tags {
|
||||
if !utl.IsIncluded(tag, opts.Include) {
|
||||
res.NotIncluded++
|
||||
continue
|
||||
} else if utl.IsExcluded(tag, opts.Exclude) {
|
||||
res.Excluded++
|
||||
continue
|
||||
}
|
||||
res.List = append(res.List, tag)
|
||||
}
|
||||
|
||||
// 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]
|
||||
for i := len(res.List)/2 - 1; i >= 0; i-- {
|
||||
opp := len(res.List) - 1 - i
|
||||
res.List[i], res.List[opp] = res.List[opp], res.List[i]
|
||||
}
|
||||
|
||||
if max > 0 && len(tags) >= max {
|
||||
return Tags(tags[:max]), len(tags), nil
|
||||
if opts.Max > 0 && len(res.List) >= opts.Max {
|
||||
res.List = res.List[:opts.Max]
|
||||
}
|
||||
|
||||
return Tags(tags), len(tags), nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user