0
0
Fork 0
mirror of https://github.com/crazy-max/diun.git synced 2025-03-15 03:44:47 +00:00

Automatically determine registry options based on image name ()

Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2020-06-22 00:19:59 +00:00 committed by GitHub
parent ca61056b3d
commit c0e3f7e85f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 287 additions and 118 deletions

View file

@ -75,14 +75,15 @@ You can define a configuration file through the option `--config` with the follo
timeout: 10s
regopts:
someregistryoptions:
- name: "myregistry"
username: foo
password: bar
timeout: 20s
onemore:
insecureTLS: true
- name: "docker.io"
selector: image
username: foo2
password: bar2
insecureTLS: true
providers:
docker:
@ -131,11 +132,16 @@ All configuration from file can be transposed into environment variables. As an
timeout: 10s
regopts:
someregistryoptions:
- name: "docker.io"
selector: image
username: foo
password: bar
- name: "registry.gitlab.com"
selector: image
username: fii
password: bor
timeout: 20s
providers:
kubernetes:
tlsInsecure: false
@ -168,9 +174,15 @@ Can be transposed to:
DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token123456
DIUN_NOTIF_WEBHOOK_TIMEOUT=10s
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_USERNAME=foo
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_PASSWORD=bar
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_TIMEOUT=20s
DIUN_REGOPTS_0_NAME=docker.io
DIUN_REGOPTS_0_SELECTOR=image
DIUN_REGOPTS_0_USERNAME=foo
DIUN_REGOPTS_0_PASSWORD=bar
DIUN_REGOPTS_1_NAME=registry.gitlab.com
DIUN_REGOPTS_1_SELECTOR=image
DIUN_REGOPTS_1_USERNAME=fii
DIUN_REGOPTS_1_PASSWORD=bor
DIUN_REGOPTS_1_TIMEOUT=20s
PROVIDERS_KUBERNETES_TLSINSECURE=false
PROVIDERS_KUBERNETES_NAMESPACES=default,production

View file

@ -1,87 +1,155 @@
# Registries options configuration
# Registry options configuration
## `username`
## Overview
Registry options is used to authenticate against a registry during the analysis of an image:
```yaml
regopts:
- name: "myregistry"
username: fii
password: bor
timeout: 5s
- name: "docker.io"
selector: image
username: foo
password: bar
- name: "docker.io/crazymax"
selector: image
usernameFile: /run/secrets/username
passwordFile: /run/secrets/password
```
`myregistry` will be used as a `name` selector (default) if referenced by its [name](#name).
`docker.io` will be used as an `image` selector. If an image is on DockerHub (`docker.io` domain), this registry options will
be selected if not referenced as a `regopt` name.
`docker.io/crazymax` will be used as an `image` selector. If an image is on DockerHub and in `crazymax` namespace, this registry options will
be selected if not referenced as a `regopt` name.
## Configuration
### `name`
Unique name for registry options. This name can be used through `diun.regopt`
[Docker](../providers/docker.md#docker-labels) / [Swarm](../providers/swarm.md#docker-labels) label
or [Kubernetes annotation](../providers/kubernetes.md#kubernetes-annotations) and also as `regopt` for the [file provider](../providers/file.md).
!!! warning
* **Required**
* Must be **unique**
!!! example "Config file"
```yaml
regopts:
- name: "myregistry"
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<KEY>_NAME`
### `selector`
What kind of selector to use to retrieve registry options. (default `name`)
!!! warning
* Accepted values are `name` or `image`
* `name` selector is the default value and will retrieve this registry options only if it's referenced by its [name](#name).
* `image` selector will retrieve this registry options if the given image matches the registry domain or repository path.
!!! example "Config file"
```yaml
regopts:
- name: "myregistry"
selector: name
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<KEY>_SELECTOR`
### `username`
Registry username.
!!! example "Config file"
```yaml
regopts:
<name>:
- name: "myregistry"
username: foo
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_USERNAME`
* `DIUN_REGOPTS_<KEY>_USERNAME`
## `usernameFile`
### `usernameFile`
Use content of secret file as registry username if `username` not defined.
!!! example "Config file"
```yaml
regopts:
<name>:
- name: "myregistry"
usernameFile: /run/secrets/username
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_USERNAMEFILE`
* `DIUN_REGOPTS_<KEY>_USERNAMEFILE`
## `password`
### `password`
Registry password.
!!! example "Config file"
```yaml
regopts:
<name>:
- name: "myregistry"
username: foo
password: bar
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_PASSWORD`
* `DIUN_REGOPTS_<KEY>_PASSWORD`
## `passwordFile`
### `passwordFile`
Use content of secret file as registry password if `password` not defined.
!!! example "Config file"
```yaml
regopts:
<name>:
usernameFile: /run/secrets/username
usernameFile: /run/secrets/password
- name: "myregistry"
passwordFile: /run/secrets/password
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_PASSWORDFILE`
* `DIUN_REGOPTS_<KEY>_PASSWORDFILE`
## `timeout`
### `timeout`
Timeout is the maximum amount of time for the TCP connection to establish. (default `10s`)
!!! example "Config file"
```yaml
regopts:
<name>:
- name: "myregistry"
timeout: 10s
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_TIMEOUT`
* `DIUN_REGOPTS_<KEY>_TIMEOUT`
## `insecureTLS`
### `insecureTLS`
Allow contacting docker registry over HTTP, or HTTPS with failed TLS verification. (default `false`)
!!! example "Config file"
```yaml
regopts:
<name>:
- name: "myregistry"
insecureTLS: false
```
!!! abstract "Environment variables"
* `DIUN_REGOPTS_<NAME>_INSECURETLS`
* `DIUN_REGOPTS_<KEY>_INSECURETLS`

View file

@ -170,7 +170,7 @@ You can configure more finely the way to analyze the image of your container thr
| Name | Default | Description |
|-------------------------------|---------------|---------------|
| `diun.enable` | | Set to true to enable image analysis of this container |
| `diun.regopts_id` | | Registry options ID from [`regopts`](../config/regopts.md) to use |
| `diun.regopt` | | Registry options name from [`regopts`](../config/regopts.md) to use |
| `diun.watch_repo` | `false` | Watch all tags of this container image |
| `diun.max_tags` | `0` | Maximum number of tags to watch if `diun.watch_repo` enabled. `0` means all of them |
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |

View file

@ -17,14 +17,18 @@ watch:
schedule: "* * * * *"
regopts:
someregistryoptions:
- name: "myregistry"
username: fii
password: bor
timeout: 5s
- name: "docker.io/crazymax"
selector: image
username: fii
password: bor
- name: "docker.io"
selector: image
username: foo
password: bar
timeout: 20
onemore:
username: foo2
password: bar2
insecureTLS: true
providers:
file:
@ -34,18 +38,20 @@ providers:
```yaml
### /path/to/config.yml
# Watch latest tag of crazymax/nextcloud image on docker.io (DockerHub) with registry ID 'someregistryoptions'.
# Watch latest tag of crazymax/nextcloud image on docker.io (DockerHub)
# with registry options named 'docker.io/crazymax' (image selector).
- name: docker.io/crazymax/nextcloud:latest
regopts_id: someregistryoptions
# Watch 4.0.0 tag of jfrog/artifactory-oss image on frog-docker-reg2.bintray.io (Bintray) with registry ID 'onemore'.
# Watch 4.0.0 tag of jfrog/artifactory-oss image on frog-docker-reg2.bintray.io (Bintray)
# with registry options named 'myregistry' (name selector).
- name: jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0
regopts_id: onemore
regopt: myregistry
# Watch coreos/hyperkube image on quay.io (Quay) and assume latest tag.
- name: quay.io/coreos/hyperkube
# Watch crazymax/swarm-cronjob image and assume docker.io registry and latest tag.
# Watch crazymax/swarm-cronjob image and assume docker.io registry and latest tag
# with registry options named 'docker.io/crazymax' (image selector).
# Only include tags matching regexp ^1\.2\..*
- name: crazymax/swarm-cronjob
watch_repo: true
@ -53,6 +59,7 @@ providers:
- ^1\.2\..*
# Watch portainer/portainer image on docker.io (DockerHub) and assume latest tag
# with registry options named 'docker.io' (image selector).
# Only watch latest 10 tags and include tags matching regexp ^(0|[1-9]\d*)\..*
- name: docker.io/portainer/portainer
watch_repo: true
@ -60,7 +67,8 @@ providers:
include_tags:
- ^(0|[1-9]\d*)\..*
# Watch alpine image (library) and assume docker.io registry and latest tag.
# Watch alpine image (library) and assume docker.io registry and latest tag
# with registry options named 'docker.io' (image selector).
# Force linux/arm64/v8 platform for this image
- name: alpine
watch_repo: true
@ -83,7 +91,8 @@ watch:
schedule: "* * * * *"
regopts:
jfrog:
- name: "docker.bintray.io"
selector: image
username: foo
password: bar
@ -97,7 +106,6 @@ providers:
- name: crazymax/cloudflared
watch_repo: true
- name: docker.bintray.io/jfrog/xray-mongo:3.2.6
regopts_id: jfrog
```
Here we want to analyze all tags of `crazymax/cloudflared` and `docker.bintray.io/jfrog/xray-mongo:3.2.6` tag. Now let's start Diun:
@ -164,7 +172,7 @@ The configuration file(s) defines a slice of images to analyze with the followin
| Name | Default | Description |
|-------------------------------|----------------------------------|---------------|
| `name` | `latest` | Docker image name to watch using `registry/path:tag` format. If registry omitted, `docker.io` will be used and if tag omitted, `latest` will be used |
| `regopts_id` | | Registry options ID from [`regopts`](../config/regopts.md) to use |
| `regopt` | | Registry options name from [`regopts`](../config/regopts.md) to use |
| `watch_repo` | `false` | Watch all tags of this image |
| `max_tags` | `0` | Maximum number of tags to watch if `watch_repo` enabled. `0` means all of them |
| `include_tags` | | List of regular expressions to include tags. Can be useful if you enable `watch_repo` |

View file

@ -273,7 +273,7 @@ You can configure more finely the way to analyze the image of your pods through
| Name | Default | Description |
|-------------------------------|---------------|---------------|
| `diun.enable` | | Set to true to enable image analysis of this pod |
| `diun.regopts_id` | | Registry options ID from [`regopts`](../config/regopts.md) to use |
| `diun.regopt` | | Registry options name from [`regopts`](../config/regopts.md) to use |
| `diun.watch_repo` | `false` | Watch all tags of this pod image |
| `diun.max_tags` | `0` | Maximum number of tags to watch if `diun.watch_repo` enabled. `0` means all of them |
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |

View file

@ -174,7 +174,7 @@ You can configure more finely the way to analyze the image of your service throu
| Name | Default | Description |
|-------------------------------|---------------|---------------|
| `diun.enable` | | Set to true to enable image analysis of this service |
| `diun.regopts_id` | | Registry options ID from [`regopts`](../config/regopts.md) to use |
| `diun.regopt` | | Registry options name to use from [`regopts`](../config/regopts.md) to use |
| `diun.watch_repo` | `false` | Watch all tags of this service image |
| `diun.max_tags` | `0` | Maximum number of tags to watch if `diun.watch_repo` enabled. `0` means all of them |
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |

View file

@ -36,19 +36,23 @@ func (di *Diun) createJob(job model.Job) {
return
}
// Registry options
regOpts, err := di.cfg.GetRegOpts(job.Image.RegOptsID)
// Get registry options
reg, err := di.cfg.RegOpts.Select(job.Image.RegOpt, job.RegImage)
if err != nil {
sublog.Warn().Err(err).Msg("Registry options")
} else if reg != nil {
sublog.Debug().Str("regopt", reg.Name).Msg("Registry options will be used")
} else {
reg = (&model.RegOpt{}).GetDefaults()
}
regUser, err := utl.GetSecret(regOpts.Username, regOpts.UsernameFile)
regUser, err := utl.GetSecret(reg.Username, reg.UsernameFile)
if err != nil {
log.Warn().Err(err).Msgf("Cannot retrieve username secret for regopts %s", job.Image.RegOptsID)
log.Warn().Err(err).Msgf("Cannot retrieve username secret for regopts %s", reg.Name)
}
regPassword, err := utl.GetSecret(regOpts.Password, regOpts.PasswordFile)
regPassword, err := utl.GetSecret(reg.Password, reg.PasswordFile)
if err != nil {
log.Warn().Err(err).Msgf("Cannot retrieve password secret for regopts %s", job.Image.RegOptsID)
log.Warn().Err(err).Msgf("Cannot retrieve password secret for regopts %s", reg.Name)
}
// Set defaults
@ -78,8 +82,8 @@ func (di *Diun) createJob(job model.Job) {
job.Registry, err = registry.New(registry.Options{
Username: regUser,
Password: regPassword,
Timeout: *regOpts.Timeout,
InsecureTLS: *regOpts.InsecureTLS,
Timeout: *reg.Timeout,
InsecureTLS: *reg.InsecureTLS,
UserAgent: di.meta.UserAgent,
ImageOs: job.Image.Platform.Os,
ImageArch: job.Image.Platform.Arch,

View file

@ -14,11 +14,11 @@ import (
// Config holds configuration details
type Config struct {
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
Watch *model.Watch `yaml:"watch,omitempty" json:"watch,omitempty"`
Notif *model.Notif `yaml:"notif,omitempty" json:"notif,omitempty"`
RegOpts map[string]*model.RegOpts `yaml:"regopts,omitempty" json:"regopts,omitempty" validate:"unique"`
Providers *model.Providers `yaml:"providers,omitempty" json:"providers,omitempty" validate:"required"`
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
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"`
}
// Load returns Configuration struct
@ -76,16 +76,6 @@ func (cfg *Config) loadEnv(out interface{}) error {
return nil
}
func (cfg *Config) GetRegOpts(id string) (*model.RegOpts, error) {
if len(id) == 0 {
return (&model.RegOpts{}).GetDefaults(), nil
}
if regopts, ok := cfg.RegOpts[id]; ok {
return regopts, nil
}
return (&model.RegOpts{}).GetDefaults(), fmt.Errorf("%s not found", id)
}
// String returns the string representation of configuration
func (cfg *Config) String() string {
b, _ := json.MarshalIndent(cfg, "", " ")

View file

@ -97,20 +97,28 @@ func TestLoadFile(t *testing.T) {
Timeout: utl.NewDuration(10 * time.Second),
},
},
RegOpts: map[string]*model.RegOpts{
"someregopts": {
RegOpts: model.RegOpts{
{
Name: "myregistry",
Selector: model.RegOptSelectorName,
Username: "fii",
Password: "bor",
InsecureTLS: utl.NewFalse(),
Timeout: utl.NewDuration(5 * time.Second),
},
"bintrayoptions": {
{
Name: "docker.io",
Selector: model.RegOptSelectorImage,
Username: "foo",
Password: "bar",
InsecureTLS: utl.NewFalse(),
Timeout: utl.NewDuration(10 * time.Second),
},
"sensitive": {
UsernameFile: "/run/secrets/username",
PasswordFile: "/run/secrets/password",
{
Name: "docker.io/crazymax",
Selector: model.RegOptSelectorImage,
UsernameFile: "./fixtures/run_secrets_username",
PasswordFile: "./fixtures/run_secrets_password",
InsecureTLS: utl.NewFalse(),
Timeout: utl.NewDuration(10 * time.Second),
},
@ -130,7 +138,7 @@ func TestLoadFile(t *testing.T) {
WatchByDefault: utl.NewTrue(),
},
File: &model.PrdFile{
Filename: "./fixtures/dummy.yml",
Filename: "./fixtures/file.yml",
},
},
},
@ -191,18 +199,22 @@ func TestLoadEnv(t *testing.T) {
{
desc: "docker provider and regopts",
environ: []string{
"DIUN_REGOPTS_SENSITIVE_USERNAMEFILE=/run/secrets/username",
"DIUN_REGOPTS_SENSITIVE_PASSWORDFILE=/run/secrets/password",
"DIUN_REGOPTS_SENSITIVE_TIMEOUT=30s",
"DIUN_REGOPTS_0_NAME=docker.io",
"DIUN_REGOPTS_0_SELECTOR=image",
"DIUN_REGOPTS_0_USERNAMEFILE=./fixtures/run_secrets_username",
"DIUN_REGOPTS_0_PASSWORDFILE=./fixtures/run_secrets_password",
"DIUN_REGOPTS_0_TIMEOUT=30s",
"DIUN_PROVIDERS_DOCKER=true",
},
expected: &config.Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
RegOpts: map[string]*model.RegOpts{
"sensitive": {
UsernameFile: "/run/secrets/username",
PasswordFile: "/run/secrets/password",
RegOpts: model.RegOpts{
{
Name: "docker.io",
Selector: model.RegOptSelectorImage,
UsernameFile: "./fixtures/run_secrets_username",
PasswordFile: "./fixtures/run_secrets_password",
InsecureTLS: utl.NewFalse(),
Timeout: utl.NewDuration(30 * time.Second),
},
@ -348,8 +360,8 @@ func TestLoadMixed(t *testing.T) {
wantErr: false,
},
{
desc: "file provider, regopts (file) and notif webhook env override",
cfgfile: "./fixtures/config.file-regopts.yml",
desc: "file provider and notif webhook env override",
cfgfile: "./fixtures/config.file.yml",
environ: []string{
"DIUN_NOTIF_WEBHOOK_ENDPOINT=http://webhook.foo.com/sd54qad89azd5a",
"DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token78910",
@ -374,7 +386,7 @@ func TestLoadMixed(t *testing.T) {
RegOpts: nil,
Providers: &model.Providers{
File: &model.PrdFile{
Filename: "./fixtures/dummy.yml",
Filename: "./fixtures/file.yml",
},
},
},

View file

@ -8,4 +8,4 @@ notif:
providers:
file:
filename: "./fixtures/dummy.yml"
filename: "./fixtures/file.yml"

View file

@ -53,14 +53,18 @@ notif:
timeout: 10s
regopts:
someregopts:
- name: "myregistry"
username: fii
password: bor
timeout: 5s
bintrayoptions:
- name: "docker.io"
selector: image
username: foo
password: bar
sensitive:
usernameFile: /run/secrets/username
passwordFile: /run/secrets/password
- name: "docker.io/crazymax"
selector: image
usernameFile: ./fixtures/run_secrets_username
passwordFile: ./fixtures/run_secrets_password
providers:
docker:
@ -70,4 +74,4 @@ providers:
kubernetes:
watchByDefault: true
file:
filename: ./fixtures/dummy.yml
filename: ./fixtures/file.yml

View file

@ -53,14 +53,16 @@ notif:
timeout: 10s
regopts:
someregopts:
- name: "myregistry"
timeout: 5s
bintrayoptions:
- name: "docker.io"
selector: image
username: foo
password: bar
sensitive:
usernameFile: /run/secrets/username
passwordFile: /run/secrets/password
- name: "docker.io/crazymax"
selector: image
usernameFile: ./fixtures/run_secrets_username
passwordFile: ./fixtures/run_secrets_username
providers:
docker:
@ -68,4 +70,4 @@ providers:
watchStopped: true
swarm: {}
file:
filename: ./fixtures/dummy.yml
filename: ./fixtures/file.yml

View file

@ -1 +0,0 @@
# noop

View file

@ -0,0 +1,24 @@
- name: docker.io/crazymax/nextcloud:latest
regopt: myregistry
- name: crazymax/swarm-cronjob
watch_repo: true
include_tags:
- ^1\.2\..*
- name: docker.io/portainer/portainer
watch_repo: true
max_tags: 10
include_tags:
- ^(0|[1-9]\d*)\..*
- name: traefik
watch_repo: true
- name: alpine
platform:
os: linux
arch: arm64
variant: v8
- name: docker.io/graylog/graylog:3.2.0
- name: jacobalberty/unifi:5.9
- name: crazymax/ddns-route53
watch_repo: true
include_tags:
- ^1\..*

View file

@ -0,0 +1 @@
bar

View file

@ -0,0 +1 @@
foo

View file

@ -28,7 +28,7 @@ func (c *Client) Migrate() error {
log.Info().Msgf("Database migration v%d...", version)
if err := migration(c); err != nil {
return errors.Wrap(err, fmt.Sprintf("Database migration v%d failed", version))
return errors.Wrapf(err, "Database migration v%d failed", version)
}
}

View file

@ -4,7 +4,7 @@ package model
type Image struct {
Name string `yaml:"name,omitempty" json:",omitempty"`
Platform ImagePlatform `yaml:"platform,omitempty" json:",omitempty"`
RegOptsID string `yaml:"regopts_id,omitempty" json:",omitempty"`
RegOpt string `yaml:"regopt,omitempty" json:",omitempty"`
WatchRepo bool `yaml:"watch_repo,omitempty" json:",omitempty"`
MaxTags int `yaml:"max_tags,omitempty" json:",omitempty"`
IncludeTags []string `yaml:"include_tags,omitempty" json:",omitempty"`

View file

@ -1,13 +1,21 @@
package model
import (
"fmt"
"strings"
"time"
"github.com/crazy-max/diun/v4/pkg/registry"
"github.com/crazy-max/diun/v4/pkg/utl"
)
// RegOpts holds registry options configuration
type RegOpts struct {
// RegOpts holds slice of registry options
type RegOpts []RegOpt
// RegOpt holds registry options configuration
type RegOpt struct {
Name string `yaml:"name,omitempty" json:"name,omitempty" validate:"required"`
Selector RegOptSelector `yaml:"selector,omitempty" json:"selector,omitempty" validate:"required,oneof=name image"`
Username string `yaml:"username,omitempty" json:"username,omitempty" validate:"omitempty"`
UsernameFile string `yaml:"usernameFile,omitempty" json:"usernameFile,omitempty" validate:"omitempty,file"`
Password string `yaml:"password,omitempty" json:"password,omitempty" validate:"omitempty"`
@ -16,15 +24,41 @@ type RegOpts struct {
Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
}
// RegOpt selector constants
const (
RegOptSelectorName = RegOptSelector("name")
RegOptSelectorImage = RegOptSelector("image")
)
// RegOptSelector holds registry options selector
type RegOptSelector string
// GetDefaults gets the default values
func (s *RegOpts) GetDefaults() *RegOpts {
n := &RegOpts{}
func (s *RegOpt) GetDefaults() *RegOpt {
n := &RegOpt{}
n.SetDefaults()
return n
}
// SetDefaults sets the default values
func (s *RegOpts) SetDefaults() {
func (s *RegOpt) SetDefaults() {
s.Selector = RegOptSelectorName
s.InsecureTLS = utl.NewFalse()
s.Timeout = utl.NewDuration(10 * time.Second)
}
// Select returns a registry based on its selector
func (s *RegOpts) Select(name string, image registry.Image) (*RegOpt, error) {
for _, regOpt := range *s {
if regOpt.Selector == RegOptSelectorName && name == regOpt.Name {
return &regOpt, nil
}
if regOpt.Selector == RegOptSelectorImage && strings.HasPrefix(image.Name(), regOpt.Name) {
return &regOpt, nil
}
}
if len(name) == 0 {
return nil, nil
}
return nil, fmt.Errorf("%s not found", name)
}

View file

@ -31,8 +31,8 @@ func ValidateContainerImage(image string, labels map[string]string, watchByDef b
for key, value := range labels {
switch key {
case "diun.regopts_id":
img.RegOptsID = value
case "diun.regopt":
img.RegOpt = value
case "diun.watch_repo":
if img.WatchRepo, err = strconv.ParseBool(value); err != nil {
return img, fmt.Errorf("cannot parse %s value of label %s", value, key)

View file

@ -13,8 +13,8 @@ var (
{
Provider: "file",
Image: model.Image{
Name: "jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0",
RegOptsID: "bintrayoptions",
Name: "jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0",
RegOpt: "bintrayoptions",
},
},
{
@ -30,8 +30,8 @@ var (
{
Provider: "file",
Image: model.Image{
Name: "docker.io/crazymax/nextcloud:latest",
RegOptsID: "someregopts",
Name: "docker.io/crazymax/nextcloud:latest",
RegOpt: "myregistry",
},
},
{

View file

@ -1,5 +1,5 @@
- name: jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0
regopts_id: bintrayoptions
regopt: bintrayoptions
- name: docker.bintray.io/jfrog/xray-server:2.8.6
watch_repo: true
max_tags: 50

View file

@ -1,5 +1,5 @@
- name: docker.io/crazymax/nextcloud:latest
regopts_id: someregopts
regopt: myregistry
- name: crazymax/swarm-cronjob
watch_repo: true
include_tags:

View file

@ -60,7 +60,7 @@ func ParseImage(parseOpts ParseImageOptions) (Image, error) {
// Parse the image name and tag.
named, err := reference.ParseNormalizedNamed(parseOpts.Name)
if err != nil {
return Image{}, errors.Wrap(err, fmt.Sprintf("parsing image %s failed", parseOpts.Name))
return Image{}, errors.Wrapf(err, "parsing image %s failed", parseOpts.Name)
}
// Add the latest lag if they did not provide one.
named = reference.TagNameOnly(named)

View file

@ -32,7 +32,7 @@ type Options struct {
// New creates new docker registry client instance
func New(opts Options) (*Client, error) {
// Auth
auth := &types.DockerAuthConfig{}
var auth *types.DockerAuthConfig
if opts.Username != "" {
auth = &types.DockerAuthConfig{
Username: opts.Username,
@ -75,6 +75,16 @@ func (c *Client) newImage(ctx context.Context, imageStr string) (types.ImageClos
return nil, errors.Wrap(err, "Invalid image name")
}
if c.sysCtx.DockerAuthConfig == nil {
c.sysCtx.DockerAuthConfig = &types.DockerAuthConfig{}
// TODO: Seek credentials
//auth, err := config.GetCredentials(c.sysCtx, reference.Domain(ref.DockerReference()))
//if err != nil {
// return nil, errors.Wrap(err, "Cannot get registry credentials")
//}
//*c.sysCtx.DockerAuthConfig = auth
}
img, err := ref.NewImage(ctx, c.sysCtx)
if err != nil {
return nil, err