Repository: crazy-max/diun
Pull request #156 (2020-08-19 06:13:41)

Bump github.com/containers/image/v5 from 5.5.1 to 5.5.2
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.5.1 to 5.5.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/containers/image/releases">github.com/containers/image/v5's releases</a>.</em></p>
<blockquote>
<h2>v5.5.2</h2>
<p>Enable search registry uses the pagination until the search result reaches the limit, instead of returning default 100 limit from registry API.
BZ: <a href="https://bugzilla.redhat.com/show_bug.cgi?id=1866153">https://bugzilla.redhat.com/show_bug.cgi?id=1866153</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/containers/image/commit/804d3bca6703717d56c5621435df340c93d4d498"><code>804d3bc</code></a> v5.5.2</li>
<li><a href="https://github.com/containers/image/commit/110a4cfe83680e26ad950b72f157a96b027e3e0d"><code>110a4cf</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/containers/image/issues/1020">#1020</a> from QiWang19/pagination-5.5</li>
<li><a href="https://github.com/containers/image/commit/d5b3990bfd6768ef488de753182b6c3f72b492a8"><code>d5b3990</code></a> backports pagination fix</li>
<li><a href="https://github.com/containers/image/commit/11bdf93f612b14d21aa1b4349569c46f9e9fc77a"><code>11bdf93</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/containers/image/issues/962">#962</a> from mtrmac/release-5.5.1</li>
<li><a href="https://github.com/containers/image/commit/57d7f407d57499d1cf947ccb6b666a014a2574b4"><code>57d7f40</code></a> Bump to v5.5.2-dev</li>
<li>See full diff in <a href="https://github.com/containers/image/compare/v5.5.1...v5.5.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/containers/image/v5&package-manager=go_modules&previous-version=5.5.1&new-version=5.5.2)](https://help.github.com/articles/configuring-automated-security-fixes)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually


</details>

codecov[bot]: # [Codecov](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=h1) Report
> Merging [#156](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=desc) into [master](https://codecov.io/gh/crazy-max/diun/commit/421348e0be9763abc13e68a11b06008849a28d23&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/crazy-max/diun/pull/156/graphs/tree.svg?width=650&height=150&src=pr&token=phc5KYIjsV)](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #156   +/-   ##
=======================================
  Coverage   70.11%   70.11%           
=======================================
  Files           7        7           
  Lines         251      251           
=======================================
  Hits          176      176           
  Misses         48       48           
  Partials       27       27           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=footer). Last update [421348e...b329c2e](https://codecov.io/gh/crazy-max/diun/pull/156?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 670bf5f6..7bc4e8a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## 4.4.1 (2020/08/20)
+
+* Allow to use `--test-notif` without providers and DB connection (#157 #150)
+* Update deps
+
 ## 4.4.0 (2020/08/08)
 
 * Allow to customize message type for Matrix notifications (#143)
diff --git a/cmd/main.go b/cmd/main.go
index bc6e954e..69d8d146 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -75,14 +75,14 @@ func main() {
 	}()
 
 	// Load configuration
-	cfg, err := config.Load(cli.Cfgfile)
+	cfg, err := config.Load(cli)
 	if err != nil {
 		log.Fatal().Err(err).Msg("Cannot load configuration")
 	}
 	log.Debug().Msg(cfg.String())
 
 	// Init
-	if diun, err = app.New(meta, cfg, location); err != nil {
+	if diun, err = app.New(meta, cli, cfg, location); err != nil {
 		log.Fatal().Err(err).Msgf("Cannot initialize %s", meta.Name)
 	}
 
diff --git a/docs/faq.md b/docs/faq.md
index 21699744..e00f96af 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -11,8 +11,7 @@ $ diun --config ./diun.yml --test-notif
 Or within a container:
 
 ```shell
-$ docker run --rm -it -v "$(pwd)/diun.yml:/diun.yml" \
-    crazymax/diun:latest --config /diun.yml --test-notif
+$ docker-compose exec diun diun --test-notif
 ```
 
 ## field docker|swarm uses unsupported type: invalid
diff --git a/go.mod b/go.mod
index 60524ca6..b878cf43 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.13
 
 require (
 	github.com/alecthomas/kong v0.2.11
-	github.com/containers/image/v5 v5.5.1
+	github.com/containers/image/v5 v5.5.2
 	github.com/crazy-max/gonfig v0.3.0
 	github.com/docker/docker v1.4.2-0.20200204220554-5f6d6f3f2203
 	github.com/docker/go-connections v0.4.0
diff --git a/go.sum b/go.sum
index e6b367d0..3dabc85a 100644
--- a/go.sum
+++ b/go.sum
@@ -58,6 +58,8 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
 github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
 github.com/containers/image/v5 v5.5.1 h1:h1FCOXH6Ux9/p/E4rndsQOC4yAdRU0msRTfLVeQ7FDQ=
 github.com/containers/image/v5 v5.5.1/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM=
+github.com/containers/image/v5 v5.5.2 h1:fv7FArz0zUnjH0W0l8t90CqWFlFcQrPP6Pug+9dUtVI=
+github.com/containers/image/v5 v5.5.2/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM=
 github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
 github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
 github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
@@ -65,8 +67,6 @@ github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNj
 github.com/containers/storage v1.20.2 h1:tw/uKRPDnmVrluIzer3dawTFG/bTJLP8IEUyHFhltYk=
 github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/crazy-max/gonfig v0.2.0 h1:xmhIS7rgd/JGAxGsVCp1dLVSEr15DOBQXvN5AvCkyhA=
-github.com/crazy-max/gonfig v0.2.0/go.mod h1:UNwOsugQKi1lY7sXRAYJNP5rftyUC5LeKyaly9Efh+c=
 github.com/crazy-max/gonfig v0.3.0 h1:/HFdLQjXSNhImgeQgD2eXhc5svX4PhUkGSbl4fJRp4s=
 github.com/crazy-max/gonfig v0.3.0/go.mod h1:7vmzltkoa1RHpGB5fTom0ebnqelHdd7fzhtXTi8sVoQ=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/internal/app/diun.go b/internal/app/diun.go
index 0ef05286..974eca10 100644
--- a/internal/app/diun.go
+++ b/internal/app/diun.go
@@ -35,28 +35,30 @@ type Diun struct {
 }
 
 // New creates new diun instance
-func New(meta model.Meta, cfg *config.Config, location *time.Location) (*Diun, error) {
-	// DB client
-	dbcli, err := db.New(*cfg.Db)
-	if err != nil {
-		return nil, err
-	}
-
-	// Notification client
-	notifcli, err := notif.New(cfg.Notif, meta)
-	if err != nil {
-		return nil, err
-	}
+func New(meta model.Meta, cli model.Cli, cfg *config.Config, location *time.Location) (*Diun, error) {
+	var err error
 
-	return &Diun{
+	diun := &Diun{
 		meta: meta,
 		cfg:  cfg,
 		cron: cron.New(cron.WithLocation(location), cron.WithParser(cron.NewParser(
 			cron.SecondOptional|cron.Minute|cron.Hour|cron.Dom|cron.Month|cron.Dow|cron.Descriptor),
 		)),
-		db:    dbcli,
-		notif: notifcli,
-	}, nil
+	}
+
+	diun.notif, err = notif.New(cfg.Notif, meta)
+	if err != nil {
+		return nil, err
+	}
+
+	if !cli.TestNotif {
+		diun.db, err = db.New(*cfg.Db)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return diun, nil
 }
 
 // Start starts diun
@@ -147,8 +149,9 @@ func (di *Diun) Close() {
 func (di *Diun) TestNotif() {
 	createdAt, _ := time.Parse("2006-01-02T15:04:05Z", "2020-03-26T12:23:56Z")
 	image, _ := registry.ParseImage(registry.ParseImageOptions{
-		Name: "crazymax/diun:latest",
+		Name: "diun/testnotif:latest",
 	})
+	image.HubLink = ""
 
 	log.Info().Msg("Testing notification settings...")
 	di.notif.Send(model.NotifEntry{
@@ -156,7 +159,7 @@ func (di *Diun) TestNotif() {
 		Provider: "file",
 		Image:    image,
 		Manifest: registry.Manifest{
-			Name:          "docker.io/crazymax/diun",
+			Name:          "diun/testnotif",
 			Tag:           "latest",
 			MIMEType:      "application/vnd.docker.distribution.manifest.list.v2+json",
 			Digest:        "sha256:216e3ae7de4ca8b553eb11ef7abda00651e79e537e85c46108284e5e91673e01",
@@ -172,7 +175,7 @@ func (di *Diun) TestNotif() {
 				"org.label-schema.vcs-ref":        "e13f097c",
 				"org.label-schema.vcs-url":        "https://github.com/crazy-max/diun",
 				"org.label-schema.vendor":         "CrazyMax",
-				"org.label-schema.version":        "2.6.1",
+				"org.label-schema.version":        "x.x.x",
 			},
 			Layers: []string{
 				"sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
diff --git a/internal/config/config.go b/internal/config/config.go
index 8b1ac32f..6bb08373 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -18,18 +18,18 @@ type Config struct {
 	Watch     *model.Watch     `yaml:"watch,omitempty" json:"watch,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" validate:"required"`
+	Providers *model.Providers `yaml:"providers,omitempty" json:"providers,omitempty"`
 }
 
 // Load returns Config struct
-func Load(cfgfile string) (*Config, error) {
+func Load(cli model.Cli) (*Config, error) {
 	cfg := Config{
 		Db:    (&model.Db{}).GetDefaults(),
 		Watch: (&model.Watch{}).GetDefaults(),
 	}
 
 	fileLoader := gonfig.NewFileLoader(gonfig.FileLoaderConfig{
-		Filename: cfgfile,
+		Filename: cli.Cfgfile,
 		Finder: gonfig.Finder{
 			BasePaths:  []string{"/etc/diun/diun", "$XDG_CONFIG_HOME/diun", "$HOME/.config/diun", "./diun"},
 			Extensions: []string{"yaml", "yml"},
@@ -54,20 +54,28 @@ func Load(cfgfile string) (*Config, error) {
 		log.Info().Msgf("Configuration loaded from %d environment variable(s)", len(envLoader.GetVars()))
 	}
 
-	if err := cfg.validate(); err != nil {
+	if err := cfg.validate(cli); err != nil {
 		return nil, err
 	}
 
 	return &cfg, nil
 }
 
-func (cfg *Config) validate() error {
+func (cfg *Config) validate(cli model.Cli) error {
 	if len(cfg.Db.Path) > 0 {
 		if err := os.MkdirAll(path.Dir(cfg.Db.Path), os.ModePerm); err != nil {
 			return errors.Wrap(err, "Cannot create database destination folder")
 		}
 	}
 
+	if cfg.Notif == nil && cli.TestNotif {
+		return errors.New("At least one notifier is required")
+	}
+
+	if cfg.Providers == nil && !cli.TestNotif {
+		return errors.New("At least one provider is required")
+	}
+
 	return validator.New().Struct(cfg)
 }
 
diff --git a/internal/db/client.go b/internal/db/client.go
index 5d5ea5b9..070c6edf 100644
--- a/internal/db/client.go
+++ b/internal/db/client.go
@@ -1,11 +1,11 @@
 package db
 
 import (
-	"fmt"
 	"reflect"
 	"time"
 
 	"github.com/crazy-max/diun/v4/internal/model"
+	"github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
 	bolt "go.etcd.io/bbolt"
 )
@@ -52,7 +52,7 @@ func New(cfg model.Db) (*Client, error) {
 		log.Debug().Msgf("%d entries found in manifest bucket", stats.KeyN)
 		return nil
 	}); err != nil {
-		return nil, fmt.Errorf("cannot count entries in manifest bucket, %v", err)
+		return nil, errors.Wrap(err, "Cannot count entries in manifest bucket")
 	}
 
 	c := &Client{


Test patch:
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 517afffb..6c91dbb4 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -18,23 +18,31 @@ import (
 func TestLoadFile(t *testing.T) {
 	cases := []struct {
 		name     string
-		cfgfile  string
+		cli      model.Cli
 		wantData *config.Config
 		wantErr  bool
 	}{
 		{
-			name:    "Failed on non-existing file",
-			cfgfile: "",
+			name: "Failed on non-existing file",
+			cli: model.Cli{
+				TestNotif: false,
+			},
 			wantErr: true,
 		},
 		{
-			name:    "Fail on wrong file format",
-			cfgfile: "./fixtures/config.invalid.yml",
+			name: "Fail on wrong file format",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.invalid.yml",
+				TestNotif: false,
+			},
 			wantErr: true,
 		},
 		{
-			name:    "Success",
-			cfgfile: "./fixtures/config.test.yml",
+			name: "Success",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.test.yml",
+				TestNotif: false,
+			},
 			wantData: &config.Config{
 				Db: &model.Db{
 					Path: "diun.db",
@@ -159,7 +167,7 @@ func TestLoadFile(t *testing.T) {
 	}
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			cfg, err := config.Load(tt.cfgfile)
+			cfg, err := config.Load(tt.cli)
 			if tt.wantErr {
 				require.Error(t, err)
 				return
@@ -178,7 +186,7 @@ func TestLoadEnv(t *testing.T) {
 
 	testCases := []struct {
 		desc     string
-		cfgfile  string
+		cli      model.Cli
 		environ  []string
 		expected interface{}
 		wantErr  bool
@@ -306,7 +314,7 @@ func TestLoadEnv(t *testing.T) {
 				}
 			}
 
-			cfg, err := config.Load(tt.cfgfile)
+			cfg, err := config.Load(tt.cli)
 			if tt.wantErr {
 				require.Error(t, err)
 				return
@@ -323,14 +331,17 @@ func TestLoadMixed(t *testing.T) {
 
 	testCases := []struct {
 		desc     string
-		cfgfile  string
+		cli      model.Cli
 		environ  []string
 		expected interface{}
 		wantErr  bool
 	}{
 		{
-			desc:    "env vars and invalid file",
-			cfgfile: "./fixtures/config.invalid.yml",
+			desc: "env vars and invalid file",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.invalid.yml",
+				TestNotif: false,
+			},
 			environ: []string{
 				"DIUN_PROVIDERS_DOCKER=true",
 			},
@@ -338,8 +349,11 @@ func TestLoadMixed(t *testing.T) {
 			wantErr:  true,
 		},
 		{
-			desc:    "docker provider (file) and notif mails (envs)",
-			cfgfile: "./fixtures/config.docker.yml",
+			desc: "docker provider (file) and notif mails (envs)",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.docker.yml",
+				TestNotif: false,
+			},
 			environ: []string{
 				"DIUN_NOTIF_MAIL_HOST=127.0.0.1",
 				"DIUN_NOTIF_MAIL_PORT=25",
@@ -373,8 +387,11 @@ func TestLoadMixed(t *testing.T) {
 			wantErr: false,
 		},
 		{
-			desc:    "file provider and notif webhook env override",
-			cfgfile: "./fixtures/config.file.yml",
+			desc: "file provider and notif webhook env override",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.file.yml",
+				TestNotif: false,
+			},
 			environ: []string{
 				"DIUN_NOTIF_WEBHOOK_ENDPOINT=http://webhook.foo.com/sd54qad89azd5a",
 				"DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token78910",
@@ -418,7 +435,7 @@ func TestLoadMixed(t *testing.T) {
 				}
 			}
 
-			cfg, err := config.Load(tt.cfgfile)
+			cfg, err := config.Load(tt.cli)
 			if tt.wantErr {
 				require.Error(t, err)
 				return
@@ -432,17 +449,20 @@ func TestLoadMixed(t *testing.T) {
 
 func TestValidation(t *testing.T) {
 	cases := []struct {
-		name    string
-		cfgfile string
+		name string
+		cli  model.Cli
 	}{
 		{
-			name:    "Success",
-			cfgfile: "./fixtures/config.validate.yml",
+			name: "Success",
+			cli: model.Cli{
+				Cfgfile:   "./fixtures/config.validate.yml",
+				TestNotif: false,
+			},
 		},
 	}
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			cfg, err := config.Load(tt.cfgfile)
+			cfg, err := config.Load(tt.cli)
 			require.NoError(t, err)
 
 			dec, err := env.Encode(cfg)