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
2 changes: 2 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ jobs:
loglevel: info
- folder: docker4
loglevel: info
- folder: docker5
loglevel: info
- folder: dockerfile1
loglevel: debug
- folder: dockerfile2
Expand Down
12 changes: 6 additions & 6 deletions internal/app/diun.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,32 +153,32 @@ func (di *Diun) Run() {
defer di.pool.Release()

// Docker provider
for _, job := range dockerPrd.New(di.cfg.Providers.Docker, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range dockerPrd.New(di.cfg.Providers.Docker, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

// Swarm provider
for _, job := range swarmPrd.New(di.cfg.Providers.Swarm, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range swarmPrd.New(di.cfg.Providers.Swarm, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

// Kubernetes provider
for _, job := range kubernetesPrd.New(di.cfg.Providers.Kubernetes, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range kubernetesPrd.New(di.cfg.Providers.Kubernetes, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

// File provider
for _, job := range filePrd.New(di.cfg.Providers.File, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range filePrd.New(di.cfg.Providers.File, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

// Dockerfile provider
for _, job := range dockerfilePrd.New(di.cfg.Providers.Dockerfile, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range dockerfilePrd.New(di.cfg.Providers.Dockerfile, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

// Nomad provider
for _, job := range nomadPrd.New(di.cfg.Providers.Nomad, di.cfg.Watch.ImageDefaults).ListJob() {
for _, job := range nomadPrd.New(di.cfg.Providers.Nomad, di.cfg.Defaults).ListJob() {
di.createJob(job)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/app/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (di *Diun) createJob(job model.Job) {
sublog.Error().Err(err).Msgf("Invoking job")
}

if job.Image.WatchRepo == nil || !*job.Image.WatchRepo || len(job.RegImage.Domain) == 0 {
if !*job.Image.WatchRepo || len(job.RegImage.Domain) == 0 {
return
}

Expand Down
6 changes: 4 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
type Config struct {
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
Watch *model.Watch `yaml:"watch,omitempty" json:"watch,omitempty"`
Defaults *model.Defaults `yaml:"defaults,omitempty" json:"defaults,omitempty"`
Notif *model.Notif `yaml:"notif,omitempty" json:"notif,omitempty"`
RegOpts model.RegOpts `yaml:"regopts,omitempty" json:"regopts,omitempty" validate:"unique=Name,dive"`
Providers *model.Providers `yaml:"providers,omitempty" json:"providers,omitempty"`
Expand All @@ -24,8 +25,9 @@ type Config struct {
// Load returns Config struct
func Load(config string) (*Config, error) {
cfg := Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
}

fileLoader := gonfig.NewFileLoader(gonfig.FileLoaderConfig{
Expand Down
44 changes: 26 additions & 18 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ func TestLoadFile(t *testing.T) {
BaseURL: "https://hc-ping.com/",
UUID: "5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278",
},
ImageDefaults: &model.Image{
NotifyOn: model.NotifyOnDefaults,
SortTags: registry.SortTagReverse,
},
},
Defaults: &model.Defaults{
WatchRepo: utl.NewFalse(),
NotifyOn: []model.NotifyOn{model.NotifyOnNew},
MaxTags: 5,
SortTags: registry.SortTagReverse,
},
Notif: &model.Notif{
Amqp: &model.NotifAmqp{
Expand Down Expand Up @@ -269,10 +271,11 @@ func TestLoadEnv(t *testing.T) {
"DIUN_PROVIDERS_DOCKER=true",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Notif: nil,
RegOpts: nil,
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
Notif: nil,
RegOpts: nil,
Providers: &model.Providers{
Docker: &model.PrdDocker{
TLSVerify: utl.NewTrue(),
Expand All @@ -294,8 +297,9 @@ func TestLoadEnv(t *testing.T) {
"DIUN_PROVIDERS_DOCKER=true",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
RegOpts: model.RegOpts{
{
Name: "docker.io",
Expand Down Expand Up @@ -324,8 +328,9 @@ func TestLoadEnv(t *testing.T) {
"DIUN_PROVIDERS_SWARM=true",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
Notif: &model.Notif{
Telegram: &model.NotifTelegram{
Token: "abcdef123456",
Expand All @@ -350,8 +355,9 @@ func TestLoadEnv(t *testing.T) {
"DIUN_PROVIDERS_FILE_DIRECTORY=./fixtures",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
Notif: &model.Notif{
Script: &model.NotifScript{
Cmd: "uname",
Expand Down Expand Up @@ -422,8 +428,9 @@ func TestLoadMixed(t *testing.T) {
"DIUN_NOTIF_MAIL_LOCALNAME=foo.com",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
Notif: &model.Notif{
Mail: &model.NotifMail{
Host: "127.0.0.1",
Expand Down Expand Up @@ -467,8 +474,9 @@ for <code>{{ .Entry.Manifest.Platform }}</code> platform.
"DIUN_NOTIF_WEBHOOK_TIMEOUT=1m",
},
expected: &Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
Notif: &model.Notif{
Webhook: &model.NotifWebhook{
Endpoint: "http://webhook.foo.com/sd54qad89azd5a",
Expand Down
5 changes: 5 additions & 0 deletions internal/config/fixtures/config.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ watch:
baseURL: https://hc-ping.com/
uuid: 5bf66975-d4c7-4bf5-bcc8-b8d8a82ea278

defaults:
notifyOn:
- new
maxTags: 5

notif:
amqp:
host: localhost
Expand Down
31 changes: 31 additions & 0 deletions internal/model/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package model

import (
"github.com/crazy-max/diun/v4/pkg/registry"
"github.com/crazy-max/diun/v4/pkg/utl"
)

// Defaults holds data necessary for image defaults configuration
type Defaults struct {
WatchRepo *bool `yaml:"watchRepo,omitempty" json:"watchRepo,omitempty"`
NotifyOn []NotifyOn `yaml:"notifyOn,omitempty" json:"notifyOn,omitempty"`
MaxTags int `yaml:"maxTags,omitempty" json:"maxTags,omitempty"`
SortTags registry.SortTag `yaml:"sortTags,omitempty" json:"sortTags,omitempty"`
IncludeTags []string `yaml:"includeTags,omitempty" json:"includeTags,omitempty"`
ExcludeTags []string `yaml:"excludeTags,omitempty" json:"excludeTags,omitempty"`
Metadata map[string]string `yaml:"metadata,omitempty" json:"metadata,omitempty"`
}

// GetDefaults gets the default values
func (s *Defaults) GetDefaults() *Defaults {
n := &Defaults{}
n.SetDefaults()
return n
}

// SetDefaults sets the default values
func (s *Defaults) SetDefaults() {
s.WatchRepo = utl.NewFalse()
s.NotifyOn = NotifyOnDefaults
s.SortTags = registry.SortTagReverse
}
6 changes: 0 additions & 6 deletions internal/model/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package model
import (
"time"

"github.com/crazy-max/diun/v4/pkg/registry"
"github.com/crazy-max/diun/v4/pkg/utl"
)

Expand All @@ -16,7 +15,6 @@ type Watch struct {
RunOnStartup *bool `yaml:"runOnStartup,omitempty" json:"runOnStartup,omitempty" validate:"required"`
CompareDigest *bool `yaml:"compareDigest,omitempty" json:"compareDigest,omitempty" validate:"required"`
Healthchecks *Healthchecks `yaml:"healthchecks,omitempty" json:"healthchecks,omitempty"`
ImageDefaults *Image `yaml:"defaults,omitempty" json:"defaults,omitempty"`
}

// GetDefaults gets the default values
Expand All @@ -33,8 +31,4 @@ func (s *Watch) SetDefaults() {
s.FirstCheckNotif = utl.NewFalse()
s.RunOnStartup = utl.NewTrue()
s.CompareDigest = utl.NewTrue()
s.ImageDefaults = &Image{
NotifyOn: NotifyOnDefaults,
SortTags: registry.SortTagReverse,
}
}
38 changes: 16 additions & 22 deletions internal/provider/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ var (
)

// ValidateImage returns a standard image through Docker labels
func ValidateImage(image string, metadata, labels map[string]string, watchByDef bool, imageDefaults model.Image) (img model.Image, err error) {
func ValidateImage(image string, metadata, labels map[string]string, watchByDef bool, defaults *model.Defaults) (img model.Image, err error) {
img = model.Image{
Name: image,
}

if err := mergo.Merge(&img, imageDefaults); err != nil {
return img, &invalidLabelError{errors.Wrapf(err, "failed to merge image defaults for image %s", image)}
if defaults != nil {
img.WatchRepo = defaults.WatchRepo
img.NotifyOn = defaults.NotifyOn
img.MaxTags = defaults.MaxTags
img.SortTags = defaults.SortTags
img.IncludeTags = defaults.IncludeTags
img.ExcludeTags = defaults.ExcludeTags
img.Metadata = defaults.Metadata
}

if enableStr, ok := labels["diun.enable"]; ok {
enable, err := strconv.ParseBool(enableStr)
if err != nil {
return img, &invalidLabelError{errors.Wrapf(err, "cannot parse %q value of label diun.enable", enableStr)}
return img, errors.Wrapf(err, "cannot parse %q value of label diun.enable", enableStr)
}
if !enable {
return model.Image{}, nil
Expand All @@ -47,7 +53,7 @@ func ValidateImage(image string, metadata, labels map[string]string, watchByDef
if watchRepo, err := strconv.ParseBool(value); err == nil {
img.WatchRepo = &watchRepo
} else {
return img, &invalidLabelError{errors.Wrapf(err, "cannot parse %q value of label %s", value, key)}
return img, errors.Wrapf(err, "cannot parse %q value of label %s", value, key)
}
case key == "diun.notify_on":
if len(value) == 0 {
Expand All @@ -57,7 +63,7 @@ func ValidateImage(image string, metadata, labels map[string]string, watchByDef
for _, no := range strings.Split(value, ";") {
notifyOn := model.NotifyOn(no)
if !notifyOn.Valid() {
return img, &invalidLabelError{errors.Errorf("unknown notify status %q", value)}
return img, errors.Errorf("unknown notify status %q", value)
}
img.NotifyOn = append(img.NotifyOn, notifyOn)
}
Expand All @@ -67,12 +73,12 @@ func ValidateImage(image string, metadata, labels map[string]string, watchByDef
}
sortTags := registry.SortTag(value)
if !sortTags.Valid() {
return img, &invalidLabelError{errors.Errorf("unknown sort tags type %q", value)}
return img, errors.Errorf("unknown sort tags type %q", value)
}
img.SortTags = sortTags
case key == "diun.max_tags":
if img.MaxTags, err = strconv.Atoi(value); err != nil {
return img, &invalidLabelError{errors.Wrapf(err, "cannot parse %q value of label %s", value, key)}
return img, errors.Wrapf(err, "cannot parse %q value of label %s", value, key)
}
case key == "diun.include_tags":
img.IncludeTags = strings.Split(value, ";")
Expand All @@ -85,7 +91,7 @@ func ValidateImage(image string, metadata, labels map[string]string, watchByDef
case key == "diun.platform":
platform, err := platforms.Parse(value)
if err != nil {
return img, &invalidLabelError{errors.Wrapf(err, "cannot parse %q platform of label %s", value, key)}
return img, errors.Wrapf(err, "cannot parse %q platform of label %s", value, key)
}
img.Platform = model.ImagePlatform{
OS: platform.OS,
Expand All @@ -98,7 +104,7 @@ func ValidateImage(image string, metadata, labels map[string]string, watchByDef
break
}
if err := validateMetadataKey(mkey); err != nil {
return img, &invalidLabelError{errors.Wrapf(err, "invalid metadata key %q", mkey)}
return img, errors.Wrapf(err, "invalid metadata key %q", mkey)
}
if img.Metadata == nil {
img.Metadata = map[string]string{}
Expand All @@ -121,15 +127,3 @@ func validateMetadataKey(key string) error {
}
return nil
}

type invalidLabelError struct {
error
}

func (e *invalidLabelError) Error() string {
return e.Error()
}

func (e *invalidLabelError) Unwrap() error {
return e
}
Loading