mirror of
https://github.com/crazy-max/diun.git
synced 2025-12-21 13:23:09 +01:00
Automatically determine registry options based on image name (#103)
Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
@@ -75,14 +75,15 @@ You can define a configuration file through the option `--config` with the follo
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
|
||||||
regopts:
|
regopts:
|
||||||
someregistryoptions:
|
- name: "myregistry"
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
timeout: 20s
|
timeout: 20s
|
||||||
onemore:
|
insecureTLS: true
|
||||||
|
- name: "docker.io"
|
||||||
|
selector: image
|
||||||
username: foo2
|
username: foo2
|
||||||
password: bar2
|
password: bar2
|
||||||
insecureTLS: true
|
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
docker:
|
docker:
|
||||||
@@ -131,11 +132,16 @@ All configuration from file can be transposed into environment variables. As an
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
|
||||||
regopts:
|
regopts:
|
||||||
someregistryoptions:
|
- name: "docker.io"
|
||||||
|
selector: image
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
|
- name: "registry.gitlab.com"
|
||||||
|
selector: image
|
||||||
|
username: fii
|
||||||
|
password: bor
|
||||||
timeout: 20s
|
timeout: 20s
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
kubernetes:
|
kubernetes:
|
||||||
tlsInsecure: false
|
tlsInsecure: false
|
||||||
@@ -168,9 +174,15 @@ Can be transposed to:
|
|||||||
DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token123456
|
DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token123456
|
||||||
DIUN_NOTIF_WEBHOOK_TIMEOUT=10s
|
DIUN_NOTIF_WEBHOOK_TIMEOUT=10s
|
||||||
|
|
||||||
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_USERNAME=foo
|
DIUN_REGOPTS_0_NAME=docker.io
|
||||||
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_PASSWORD=bar
|
DIUN_REGOPTS_0_SELECTOR=image
|
||||||
DIUN_REGOPTS_SOMEREGISTRYOPTIONS_TIMEOUT=20s
|
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_TLSINSECURE=false
|
||||||
PROVIDERS_KUBERNETES_NAMESPACES=default,production
|
PROVIDERS_KUBERNETES_NAMESPACES=default,production
|
||||||
|
|||||||
@@ -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.
|
Registry username.
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
username: foo
|
username: foo
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! 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.
|
Use content of secret file as registry username if `username` not defined.
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
usernameFile: /run/secrets/username
|
usernameFile: /run/secrets/username
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! abstract "Environment variables"
|
||||||
* `DIUN_REGOPTS_<NAME>_USERNAMEFILE`
|
* `DIUN_REGOPTS_<KEY>_USERNAMEFILE`
|
||||||
|
|
||||||
## `password`
|
### `password`
|
||||||
|
|
||||||
Registry password.
|
Registry password.
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! 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.
|
Use content of secret file as registry password if `password` not defined.
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
usernameFile: /run/secrets/username
|
passwordFile: /run/secrets/password
|
||||||
usernameFile: /run/secrets/password
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! 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`)
|
Timeout is the maximum amount of time for the TCP connection to establish. (default `10s`)
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! 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`)
|
Allow contacting docker registry over HTTP, or HTTPS with failed TLS verification. (default `false`)
|
||||||
|
|
||||||
!!! example "Config file"
|
!!! example "Config file"
|
||||||
```yaml
|
```yaml
|
||||||
regopts:
|
regopts:
|
||||||
<name>:
|
- name: "myregistry"
|
||||||
insecureTLS: false
|
insecureTLS: false
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! abstract "Environment variables"
|
!!! abstract "Environment variables"
|
||||||
* `DIUN_REGOPTS_<NAME>_INSECURETLS`
|
* `DIUN_REGOPTS_<KEY>_INSECURETLS`
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ You can configure more finely the way to analyze the image of your container thr
|
|||||||
| Name | Default | Description |
|
| Name | Default | Description |
|
||||||
|-------------------------------|---------------|---------------|
|
|-------------------------------|---------------|---------------|
|
||||||
| `diun.enable` | | Set to true to enable image analysis of this container |
|
| `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.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.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` |
|
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |
|
||||||
|
|||||||
@@ -17,14 +17,18 @@ watch:
|
|||||||
schedule: "* * * * *"
|
schedule: "* * * * *"
|
||||||
|
|
||||||
regopts:
|
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
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
timeout: 20
|
|
||||||
onemore:
|
|
||||||
username: foo2
|
|
||||||
password: bar2
|
|
||||||
insecureTLS: true
|
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
file:
|
file:
|
||||||
@@ -34,18 +38,20 @@ providers:
|
|||||||
```yaml
|
```yaml
|
||||||
### /path/to/config.yml
|
### /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
|
- 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
|
- 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.
|
# Watch coreos/hyperkube image on quay.io (Quay) and assume latest tag.
|
||||||
- name: quay.io/coreos/hyperkube
|
- 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\..*
|
# Only include tags matching regexp ^1\.2\..*
|
||||||
- name: crazymax/swarm-cronjob
|
- name: crazymax/swarm-cronjob
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
@@ -53,6 +59,7 @@ providers:
|
|||||||
- ^1\.2\..*
|
- ^1\.2\..*
|
||||||
|
|
||||||
# Watch portainer/portainer image on docker.io (DockerHub) and assume latest tag
|
# 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*)\..*
|
# Only watch latest 10 tags and include tags matching regexp ^(0|[1-9]\d*)\..*
|
||||||
- name: docker.io/portainer/portainer
|
- name: docker.io/portainer/portainer
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
@@ -60,7 +67,8 @@ providers:
|
|||||||
include_tags:
|
include_tags:
|
||||||
- ^(0|[1-9]\d*)\..*
|
- ^(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
|
# Force linux/arm64/v8 platform for this image
|
||||||
- name: alpine
|
- name: alpine
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
@@ -83,7 +91,8 @@ watch:
|
|||||||
schedule: "* * * * *"
|
schedule: "* * * * *"
|
||||||
|
|
||||||
regopts:
|
regopts:
|
||||||
jfrog:
|
- name: "docker.bintray.io"
|
||||||
|
selector: image
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
|
|
||||||
@@ -97,7 +106,6 @@ providers:
|
|||||||
- name: crazymax/cloudflared
|
- name: crazymax/cloudflared
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
- name: docker.bintray.io/jfrog/xray-mongo:3.2.6
|
- 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:
|
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 | 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 |
|
| `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 |
|
| `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 |
|
| `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` |
|
| `include_tags` | | List of regular expressions to include tags. Can be useful if you enable `watch_repo` |
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ You can configure more finely the way to analyze the image of your pods through
|
|||||||
| Name | Default | Description |
|
| Name | Default | Description |
|
||||||
|-------------------------------|---------------|---------------|
|
|-------------------------------|---------------|---------------|
|
||||||
| `diun.enable` | | Set to true to enable image analysis of this pod |
|
| `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.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.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` |
|
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ You can configure more finely the way to analyze the image of your service throu
|
|||||||
| Name | Default | Description |
|
| Name | Default | Description |
|
||||||
|-------------------------------|---------------|---------------|
|
|-------------------------------|---------------|---------------|
|
||||||
| `diun.enable` | | Set to true to enable image analysis of this service |
|
| `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.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.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` |
|
| `diun.include_tags` | | Semi-colon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |
|
||||||
|
|||||||
@@ -36,19 +36,23 @@ func (di *Diun) createJob(job model.Job) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registry options
|
// Get registry options
|
||||||
regOpts, err := di.cfg.GetRegOpts(job.Image.RegOptsID)
|
reg, err := di.cfg.RegOpts.Select(job.Image.RegOpt, job.RegImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sublog.Warn().Err(err).Msg("Registry options")
|
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 {
|
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 {
|
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
|
// Set defaults
|
||||||
@@ -78,8 +82,8 @@ func (di *Diun) createJob(job model.Job) {
|
|||||||
job.Registry, err = registry.New(registry.Options{
|
job.Registry, err = registry.New(registry.Options{
|
||||||
Username: regUser,
|
Username: regUser,
|
||||||
Password: regPassword,
|
Password: regPassword,
|
||||||
Timeout: *regOpts.Timeout,
|
Timeout: *reg.Timeout,
|
||||||
InsecureTLS: *regOpts.InsecureTLS,
|
InsecureTLS: *reg.InsecureTLS,
|
||||||
UserAgent: di.meta.UserAgent,
|
UserAgent: di.meta.UserAgent,
|
||||||
ImageOs: job.Image.Platform.Os,
|
ImageOs: job.Image.Platform.Os,
|
||||||
ImageArch: job.Image.Platform.Arch,
|
ImageArch: job.Image.Platform.Arch,
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import (
|
|||||||
|
|
||||||
// Config holds configuration details
|
// Config holds configuration details
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
|
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
|
||||||
Watch *model.Watch `yaml:"watch,omitempty" json:"watch,omitempty"`
|
Watch *model.Watch `yaml:"watch,omitempty" json:"watch,omitempty"`
|
||||||
Notif *model.Notif `yaml:"notif,omitempty" json:"notif,omitempty"`
|
Notif *model.Notif `yaml:"notif,omitempty" json:"notif,omitempty"`
|
||||||
RegOpts map[string]*model.RegOpts `yaml:"regopts,omitempty" json:"regopts,omitempty" validate:"unique"`
|
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" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load returns Configuration struct
|
// Load returns Configuration struct
|
||||||
@@ -76,16 +76,6 @@ func (cfg *Config) loadEnv(out interface{}) error {
|
|||||||
return nil
|
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
|
// String returns the string representation of configuration
|
||||||
func (cfg *Config) String() string {
|
func (cfg *Config) String() string {
|
||||||
b, _ := json.MarshalIndent(cfg, "", " ")
|
b, _ := json.MarshalIndent(cfg, "", " ")
|
||||||
|
|||||||
@@ -97,20 +97,28 @@ func TestLoadFile(t *testing.T) {
|
|||||||
Timeout: utl.NewDuration(10 * time.Second),
|
Timeout: utl.NewDuration(10 * time.Second),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RegOpts: map[string]*model.RegOpts{
|
RegOpts: model.RegOpts{
|
||||||
"someregopts": {
|
{
|
||||||
|
Name: "myregistry",
|
||||||
|
Selector: model.RegOptSelectorName,
|
||||||
|
Username: "fii",
|
||||||
|
Password: "bor",
|
||||||
InsecureTLS: utl.NewFalse(),
|
InsecureTLS: utl.NewFalse(),
|
||||||
Timeout: utl.NewDuration(5 * time.Second),
|
Timeout: utl.NewDuration(5 * time.Second),
|
||||||
},
|
},
|
||||||
"bintrayoptions": {
|
{
|
||||||
|
Name: "docker.io",
|
||||||
|
Selector: model.RegOptSelectorImage,
|
||||||
Username: "foo",
|
Username: "foo",
|
||||||
Password: "bar",
|
Password: "bar",
|
||||||
InsecureTLS: utl.NewFalse(),
|
InsecureTLS: utl.NewFalse(),
|
||||||
Timeout: utl.NewDuration(10 * time.Second),
|
Timeout: utl.NewDuration(10 * time.Second),
|
||||||
},
|
},
|
||||||
"sensitive": {
|
{
|
||||||
UsernameFile: "/run/secrets/username",
|
Name: "docker.io/crazymax",
|
||||||
PasswordFile: "/run/secrets/password",
|
Selector: model.RegOptSelectorImage,
|
||||||
|
UsernameFile: "./fixtures/run_secrets_username",
|
||||||
|
PasswordFile: "./fixtures/run_secrets_password",
|
||||||
InsecureTLS: utl.NewFalse(),
|
InsecureTLS: utl.NewFalse(),
|
||||||
Timeout: utl.NewDuration(10 * time.Second),
|
Timeout: utl.NewDuration(10 * time.Second),
|
||||||
},
|
},
|
||||||
@@ -130,7 +138,7 @@ func TestLoadFile(t *testing.T) {
|
|||||||
WatchByDefault: utl.NewTrue(),
|
WatchByDefault: utl.NewTrue(),
|
||||||
},
|
},
|
||||||
File: &model.PrdFile{
|
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",
|
desc: "docker provider and regopts",
|
||||||
environ: []string{
|
environ: []string{
|
||||||
"DIUN_REGOPTS_SENSITIVE_USERNAMEFILE=/run/secrets/username",
|
"DIUN_REGOPTS_0_NAME=docker.io",
|
||||||
"DIUN_REGOPTS_SENSITIVE_PASSWORDFILE=/run/secrets/password",
|
"DIUN_REGOPTS_0_SELECTOR=image",
|
||||||
"DIUN_REGOPTS_SENSITIVE_TIMEOUT=30s",
|
"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",
|
"DIUN_PROVIDERS_DOCKER=true",
|
||||||
},
|
},
|
||||||
expected: &config.Config{
|
expected: &config.Config{
|
||||||
Db: (&model.Db{}).GetDefaults(),
|
Db: (&model.Db{}).GetDefaults(),
|
||||||
Watch: (&model.Watch{}).GetDefaults(),
|
Watch: (&model.Watch{}).GetDefaults(),
|
||||||
RegOpts: map[string]*model.RegOpts{
|
RegOpts: model.RegOpts{
|
||||||
"sensitive": {
|
{
|
||||||
UsernameFile: "/run/secrets/username",
|
Name: "docker.io",
|
||||||
PasswordFile: "/run/secrets/password",
|
Selector: model.RegOptSelectorImage,
|
||||||
|
UsernameFile: "./fixtures/run_secrets_username",
|
||||||
|
PasswordFile: "./fixtures/run_secrets_password",
|
||||||
InsecureTLS: utl.NewFalse(),
|
InsecureTLS: utl.NewFalse(),
|
||||||
Timeout: utl.NewDuration(30 * time.Second),
|
Timeout: utl.NewDuration(30 * time.Second),
|
||||||
},
|
},
|
||||||
@@ -348,8 +360,8 @@ func TestLoadMixed(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "file provider, regopts (file) and notif webhook env override",
|
desc: "file provider and notif webhook env override",
|
||||||
cfgfile: "./fixtures/config.file-regopts.yml",
|
cfgfile: "./fixtures/config.file.yml",
|
||||||
environ: []string{
|
environ: []string{
|
||||||
"DIUN_NOTIF_WEBHOOK_ENDPOINT=http://webhook.foo.com/sd54qad89azd5a",
|
"DIUN_NOTIF_WEBHOOK_ENDPOINT=http://webhook.foo.com/sd54qad89azd5a",
|
||||||
"DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token78910",
|
"DIUN_NOTIF_WEBHOOK_HEADERS_AUTHORIZATION=Token78910",
|
||||||
@@ -374,7 +386,7 @@ func TestLoadMixed(t *testing.T) {
|
|||||||
RegOpts: nil,
|
RegOpts: nil,
|
||||||
Providers: &model.Providers{
|
Providers: &model.Providers{
|
||||||
File: &model.PrdFile{
|
File: &model.PrdFile{
|
||||||
Filename: "./fixtures/dummy.yml",
|
Filename: "./fixtures/file.yml",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ notif:
|
|||||||
|
|
||||||
providers:
|
providers:
|
||||||
file:
|
file:
|
||||||
filename: "./fixtures/dummy.yml"
|
filename: "./fixtures/file.yml"
|
||||||
@@ -53,14 +53,18 @@ notif:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
|
||||||
regopts:
|
regopts:
|
||||||
someregopts:
|
- name: "myregistry"
|
||||||
|
username: fii
|
||||||
|
password: bor
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
bintrayoptions:
|
- name: "docker.io"
|
||||||
|
selector: image
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
sensitive:
|
- name: "docker.io/crazymax"
|
||||||
usernameFile: /run/secrets/username
|
selector: image
|
||||||
passwordFile: /run/secrets/password
|
usernameFile: ./fixtures/run_secrets_username
|
||||||
|
passwordFile: ./fixtures/run_secrets_password
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
docker:
|
docker:
|
||||||
@@ -70,4 +74,4 @@ providers:
|
|||||||
kubernetes:
|
kubernetes:
|
||||||
watchByDefault: true
|
watchByDefault: true
|
||||||
file:
|
file:
|
||||||
filename: ./fixtures/dummy.yml
|
filename: ./fixtures/file.yml
|
||||||
|
|||||||
@@ -53,14 +53,16 @@ notif:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
|
||||||
regopts:
|
regopts:
|
||||||
someregopts:
|
- name: "myregistry"
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
bintrayoptions:
|
- name: "docker.io"
|
||||||
|
selector: image
|
||||||
username: foo
|
username: foo
|
||||||
password: bar
|
password: bar
|
||||||
sensitive:
|
- name: "docker.io/crazymax"
|
||||||
usernameFile: /run/secrets/username
|
selector: image
|
||||||
passwordFile: /run/secrets/password
|
usernameFile: ./fixtures/run_secrets_username
|
||||||
|
passwordFile: ./fixtures/run_secrets_username
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
docker:
|
docker:
|
||||||
@@ -68,4 +70,4 @@ providers:
|
|||||||
watchStopped: true
|
watchStopped: true
|
||||||
swarm: {}
|
swarm: {}
|
||||||
file:
|
file:
|
||||||
filename: ./fixtures/dummy.yml
|
filename: ./fixtures/file.yml
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
# noop
|
|
||||||
24
internal/config/fixtures/file.yml
Normal file
24
internal/config/fixtures/file.yml
Normal 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\..*
|
||||||
1
internal/config/fixtures/run_secrets_password
Normal file
1
internal/config/fixtures/run_secrets_password
Normal file
@@ -0,0 +1 @@
|
|||||||
|
bar
|
||||||
1
internal/config/fixtures/run_secrets_username
Normal file
1
internal/config/fixtures/run_secrets_username
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo
|
||||||
@@ -28,7 +28,7 @@ func (c *Client) Migrate() error {
|
|||||||
|
|
||||||
log.Info().Msgf("Database migration v%d...", version)
|
log.Info().Msgf("Database migration v%d...", version)
|
||||||
if err := migration(c); err != nil {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package model
|
|||||||
type Image struct {
|
type Image struct {
|
||||||
Name string `yaml:"name,omitempty" json:",omitempty"`
|
Name string `yaml:"name,omitempty" json:",omitempty"`
|
||||||
Platform ImagePlatform `yaml:"platform,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"`
|
WatchRepo bool `yaml:"watch_repo,omitempty" json:",omitempty"`
|
||||||
MaxTags int `yaml:"max_tags,omitempty" json:",omitempty"`
|
MaxTags int `yaml:"max_tags,omitempty" json:",omitempty"`
|
||||||
IncludeTags []string `yaml:"include_tags,omitempty" json:",omitempty"`
|
IncludeTags []string `yaml:"include_tags,omitempty" json:",omitempty"`
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/crazy-max/diun/v4/pkg/registry"
|
||||||
"github.com/crazy-max/diun/v4/pkg/utl"
|
"github.com/crazy-max/diun/v4/pkg/utl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegOpts holds registry options configuration
|
// RegOpts holds slice of registry options
|
||||||
type RegOpts struct {
|
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"`
|
Username string `yaml:"username,omitempty" json:"username,omitempty" validate:"omitempty"`
|
||||||
UsernameFile string `yaml:"usernameFile,omitempty" json:"usernameFile,omitempty" validate:"omitempty,file"`
|
UsernameFile string `yaml:"usernameFile,omitempty" json:"usernameFile,omitempty" validate:"omitempty,file"`
|
||||||
Password string `yaml:"password,omitempty" json:"password,omitempty" validate:"omitempty"`
|
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"`
|
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
|
// GetDefaults gets the default values
|
||||||
func (s *RegOpts) GetDefaults() *RegOpts {
|
func (s *RegOpt) GetDefaults() *RegOpt {
|
||||||
n := &RegOpts{}
|
n := &RegOpt{}
|
||||||
n.SetDefaults()
|
n.SetDefaults()
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values
|
// SetDefaults sets the default values
|
||||||
func (s *RegOpts) SetDefaults() {
|
func (s *RegOpt) SetDefaults() {
|
||||||
|
s.Selector = RegOptSelectorName
|
||||||
s.InsecureTLS = utl.NewFalse()
|
s.InsecureTLS = utl.NewFalse()
|
||||||
s.Timeout = utl.NewDuration(10 * time.Second)
|
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 ®Opt, nil
|
||||||
|
}
|
||||||
|
if regOpt.Selector == RegOptSelectorImage && strings.HasPrefix(image.Name(), regOpt.Name) {
|
||||||
|
return ®Opt, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("%s not found", name)
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ func ValidateContainerImage(image string, labels map[string]string, watchByDef b
|
|||||||
|
|
||||||
for key, value := range labels {
|
for key, value := range labels {
|
||||||
switch key {
|
switch key {
|
||||||
case "diun.regopts_id":
|
case "diun.regopt":
|
||||||
img.RegOptsID = value
|
img.RegOpt = value
|
||||||
case "diun.watch_repo":
|
case "diun.watch_repo":
|
||||||
if img.WatchRepo, err = strconv.ParseBool(value); err != nil {
|
if img.WatchRepo, err = strconv.ParseBool(value); err != nil {
|
||||||
return img, fmt.Errorf("cannot parse %s value of label %s", value, key)
|
return img, fmt.Errorf("cannot parse %s value of label %s", value, key)
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ var (
|
|||||||
{
|
{
|
||||||
Provider: "file",
|
Provider: "file",
|
||||||
Image: model.Image{
|
Image: model.Image{
|
||||||
Name: "jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0",
|
Name: "jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0",
|
||||||
RegOptsID: "bintrayoptions",
|
RegOpt: "bintrayoptions",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -30,8 +30,8 @@ var (
|
|||||||
{
|
{
|
||||||
Provider: "file",
|
Provider: "file",
|
||||||
Image: model.Image{
|
Image: model.Image{
|
||||||
Name: "docker.io/crazymax/nextcloud:latest",
|
Name: "docker.io/crazymax/nextcloud:latest",
|
||||||
RegOptsID: "someregopts",
|
RegOpt: "myregistry",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
- name: jfrog-docker-reg2.bintray.io/jfrog/artifactory-oss:4.0.0
|
- 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
|
- name: docker.bintray.io/jfrog/xray-server:2.8.6
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
max_tags: 50
|
max_tags: 50
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
- name: docker.io/crazymax/nextcloud:latest
|
- name: docker.io/crazymax/nextcloud:latest
|
||||||
regopts_id: someregopts
|
regopt: myregistry
|
||||||
- name: crazymax/swarm-cronjob
|
- name: crazymax/swarm-cronjob
|
||||||
watch_repo: true
|
watch_repo: true
|
||||||
include_tags:
|
include_tags:
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func ParseImage(parseOpts ParseImageOptions) (Image, error) {
|
|||||||
// Parse the image name and tag.
|
// Parse the image name and tag.
|
||||||
named, err := reference.ParseNormalizedNamed(parseOpts.Name)
|
named, err := reference.ParseNormalizedNamed(parseOpts.Name)
|
||||||
if err != nil {
|
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.
|
// Add the latest lag if they did not provide one.
|
||||||
named = reference.TagNameOnly(named)
|
named = reference.TagNameOnly(named)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ type Options struct {
|
|||||||
// New creates new docker registry client instance
|
// New creates new docker registry client instance
|
||||||
func New(opts Options) (*Client, error) {
|
func New(opts Options) (*Client, error) {
|
||||||
// Auth
|
// Auth
|
||||||
auth := &types.DockerAuthConfig{}
|
var auth *types.DockerAuthConfig
|
||||||
if opts.Username != "" {
|
if opts.Username != "" {
|
||||||
auth = &types.DockerAuthConfig{
|
auth = &types.DockerAuthConfig{
|
||||||
Username: opts.Username,
|
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")
|
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)
|
img, err := ref.NewImage(ctx, c.sysCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user