Skip to content

Commit

Permalink
Filter tags before return them
Browse files Browse the repository at this point in the history
  • Loading branch information
crazy-max committed Jun 8, 2019
1 parent 6648721 commit 4742827
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 42 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -141,7 +141,7 @@ items:
watch_repo: true
max_tags: 10
include_tags:
- ^(0|[1-9]\d*)\.*
- ^(0|[1-9]\d*)\..*
```
* `db`
Expand Down
45 changes: 16 additions & 29 deletions internal/app/diun.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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")
Expand All @@ -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())
}
28 changes: 28 additions & 0 deletions internal/utl/utl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
53 changes: 42 additions & 11 deletions pkg/docker/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 4742827

Please sign in to comment.