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
|
# Changelog
|
||||||
|
|
||||||
|
## 0.4.1 (2019/06/08)
|
||||||
|
|
||||||
|
* Filter tags before return them
|
||||||
|
|
||||||
## 0.4.0 (2019/06/08)
|
## 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
|
* 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
|
$ 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.
|
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
|
watch_repo: true
|
||||||
max_tags: 10
|
max_tags: 10
|
||||||
include_tags:
|
include_tags:
|
||||||
- ^(0|[1-9]\d*)\.*
|
- ^(0|[1-9]\d*)\..*
|
||||||
```
|
```
|
||||||
|
|
||||||
* `db`
|
* `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)
|
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)
|
log.Warn().Str("image", image.String()).Msgf("Tag %s not included", image.Tag)
|
||||||
return image, nil
|
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)
|
log.Warn().Str("image", image.String()).Msgf("Tag %s excluded", image.Tag)
|
||||||
return image, nil
|
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) {
|
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 {
|
if err != nil {
|
||||||
log.Error().Err(err).Str("image", image.String()).Msg("Cannot retrieve tags")
|
log.Error().Err(err).Str("image", image.String()).Msg("Cannot retrieve tags")
|
||||||
return
|
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)
|
imageStr := fmt.Sprintf("%s/%s:%s", image.Domain, image.Path, tag)
|
||||||
if _, err := di.analyzeImage(imageStr, item, reg); err != nil {
|
if _, err := di.analyzeImage(imageStr, item, reg); err != nil {
|
||||||
log.Error().Err(err).Str("image", imageStr).Msg("Cannot analyze image")
|
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) {
|
func (di *Diun) trackTime(start time.Time, prefix string) {
|
||||||
log.Info().Msgf("%s%s", prefix, durafmt.ParseShort(time.Since(start)).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)
|
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 (
|
import (
|
||||||
"github.com/containers/image/docker"
|
"github.com/containers/image/docker"
|
||||||
|
"github.com/crazy-max/diun/internal/utl"
|
||||||
"github.com/crazy-max/diun/pkg/docker/registry"
|
"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
|
// 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()
|
ctx, cancel := c.timeoutContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
imgCls, err := c.newImage(ctx, image.String())
|
imgCls, err := c.newImage(ctx, opts.Image.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer imgCls.Close()
|
defer imgCls.Close()
|
||||||
|
|
||||||
tags, err := docker.GetRepositoryTags(ctx, c.sysCtx, imgCls.Reference())
|
tags, err := docker.GetRepositoryTags(ctx, c.sysCtx, imgCls.Reference())
|
||||||
if err != nil {
|
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)
|
// Reverse order (latest tags first)
|
||||||
for i := len(tags)/2 - 1; i >= 0; i-- {
|
for i := len(res.List)/2 - 1; i >= 0; i-- {
|
||||||
opp := len(tags) - 1 - i
|
opp := len(res.List) - 1 - i
|
||||||
tags[i], tags[opp] = tags[opp], tags[i]
|
res.List[i], res.List[opp] = res.List[opp], res.List[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if max > 0 && len(tags) >= max {
|
if opts.Max > 0 && len(res.List) >= opts.Max {
|
||||||
return Tags(tags[:max]), len(tags), nil
|
res.List = res.List[:opts.Max]
|
||||||
}
|
}
|
||||||
|
|
||||||
return Tags(tags), len(tags), nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user