mirror of
https://github.com/containrrr/watchtower.git
synced 2025-12-16 15:10:12 +01:00
Merge branch 'main' into fix/ref-processing
This commit is contained in:
commit
c5c37f8795
26 changed files with 945 additions and 189 deletions
8
.github/workflows/pull-request.yml
vendored
8
.github/workflows/pull-request.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- uses: dominikh/staticcheck-action@ba605356b4b29a60e87ab9404b712f3461e566dc #v1.3.0
|
- uses: dominikh/staticcheck-action@ba605356b4b29a60e87ab9404b712f3461e566dc #v1.3.0
|
||||||
|
|
@ -41,7 +41,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
|
@ -60,11 +60,11 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- name: Build
|
- name: Build
|
||||||
uses: goreleaser/goreleaser-action@8f67e590f2d095516493f017008adc464e63adb1 #v3
|
uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b #v3
|
||||||
with:
|
with:
|
||||||
version: v0.155.0
|
version: v0.155.0
|
||||||
args: --snapshot --skip-publish --debug
|
args: --snapshot --skip-publish --debug
|
||||||
|
|
|
||||||
4
.github/workflows/release-dev.yaml
vendored
4
.github/workflows/release-dev.yaml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: 1.18
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|
@ -22,7 +22,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: 1.18
|
||||||
- name: Test
|
- name: Test
|
||||||
|
|
|
||||||
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- uses: dominikh/staticcheck-action@ba605356b4b29a60e87ab9404b712f3461e566dc #v1.3.0
|
- uses: dominikh/staticcheck-action@ba605356b4b29a60e87ab9404b712f3461e566dc #v1.3.0
|
||||||
|
|
@ -44,7 +44,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
|
@ -66,7 +66,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.18.x
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
|
|
@ -81,7 +81,7 @@ jobs:
|
||||||
password: ${{ secrets.BOT_GHCR_PAT }}
|
password: ${{ secrets.BOT_GHCR_PAT }}
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
- name: Build
|
- name: Build
|
||||||
uses: goreleaser/goreleaser-action@8f67e590f2d095516493f017008adc464e63adb1 #v3
|
uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b #v3
|
||||||
with:
|
with:
|
||||||
version: v0.155.0
|
version: v0.155.0
|
||||||
args: --debug
|
args: --debug
|
||||||
|
|
@ -191,7 +191,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Pull new module version
|
- name: Pull new module version
|
||||||
uses: andrewslotin/go-proxy-pull-action@bfc19ec6536e1638181b2ad6a03e16c7ccfb122f #master@2022-10-14
|
uses: andrewslotin/go-proxy-pull-action@50fea06a976087614babb9508e5c528b464f4645 #master@2022-10-14
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,10 @@ func Run(c *cobra.Command, names []string) {
|
||||||
httpAPI := api.New(apiToken)
|
httpAPI := api.New(apiToken)
|
||||||
|
|
||||||
if enableUpdateAPI {
|
if enableUpdateAPI {
|
||||||
updateHandler := update.New(func(images []string) { runUpdatesWithNotifications(filters.FilterByImage(images, filter)) }, updateLock)
|
updateHandler := update.New(func(images []string) {
|
||||||
|
metric := runUpdatesWithNotifications(filters.FilterByImage(images, filter))
|
||||||
|
metrics.RegisterScan(metric)
|
||||||
|
}, updateLock)
|
||||||
httpAPI.RegisterFunc(updateHandler.Path, updateHandler.Handle)
|
httpAPI.RegisterFunc(updateHandler.Path, updateHandler.Handle)
|
||||||
// If polling isn't enabled the scheduler is never started and
|
// If polling isn't enabled the scheduler is never started and
|
||||||
// we need to trigger the startup messages manually.
|
// we need to trigger the startup messages manually.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
FROM --platform=$BUILDPLATFORM alpine:3.17.1 as alpine
|
FROM --platform=$BUILDPLATFORM alpine:3.17.3 as alpine
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,9 @@ Environment Variable: WATCHTOWER_NO_PULL
|
||||||
Default: false
|
Default: false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that no-pull can also be specified on a per-container basis with the
|
||||||
|
`com.centurylinklabs.watchtower.no-pull` label set on those containers.
|
||||||
|
|
||||||
## Without sending a startup message
|
## Without sending a startup message
|
||||||
Do not send a message after watchtower started. Otherwise there will be an info-level notification.
|
Do not send a message after watchtower started. Otherwise there will be an info-level notification.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ To send notifications via shoutrrr, the following command-line options, or their
|
||||||
- `--notification-url` (env. `WATCHTOWER_NOTIFICATION_URL`): The shoutrrr service URL to be used. This option can also reference a file, in which case the contents of the file are used.
|
- `--notification-url` (env. `WATCHTOWER_NOTIFICATION_URL`): The shoutrrr service URL to be used. This option can also reference a file, in which case the contents of the file are used.
|
||||||
|
|
||||||
|
|
||||||
Go to [containrrr.dev/shoutrrr/v0.6/services/overview](https://containrrr.dev/shoutrrr/v0.6/services/overview) to
|
Go to [containrrr.dev/shoutrrr/v0.7/services/overview](https://containrrr.dev/shoutrrr/v0.6/services/overview) to
|
||||||
learn more about the different service URLs you can use. You can define multiple services by space separating the
|
learn more about the different service URLs you can use. You can define multiple services by space separating the
|
||||||
URLs. (See example below)
|
URLs. (See example below)
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ Example using a custom report template that always sends a session report after
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name watchtower \
|
--name watchtower \
|
||||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
-e WATCHTOWER_NOTIFICATION_REPORT="true"
|
-e WATCHTOWER_NOTIFICATION_REPORT="true" \
|
||||||
-e WATCHTOWER_NOTIFICATION_URL="discord://token@channel slack://watchtower@token-a/token-b/token-c" \
|
-e WATCHTOWER_NOTIFICATION_URL="discord://token@channel slack://watchtower@token-a/token-b/token-c" \
|
||||||
-e WATCHTOWER_NOTIFICATION_TEMPLATE="
|
-e WATCHTOWER_NOTIFICATION_TEMPLATE="
|
||||||
{{- if .Report -}}
|
{{- if .Report -}}
|
||||||
|
|
@ -130,7 +130,7 @@ Example using a custom report template that always sends a session report after
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
{{range .Entries -}}{{.Message}}{{"\n"}}{{- end -}}
|
{{range .Entries -}}{{.Message}}{{\"\n\"}}{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
" \
|
" \
|
||||||
containrrr/watchtower
|
containrrr/watchtower
|
||||||
|
|
|
||||||
42
go.mod
42
go.mod
|
|
@ -3,21 +3,21 @@ module github.com/containrrr/watchtower
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containrrr/shoutrrr v0.6.1
|
github.com/containrrr/shoutrrr v0.7.1
|
||||||
github.com/docker/cli v20.10.22+incompatible
|
github.com/docker/cli v23.0.3+incompatible
|
||||||
github.com/docker/distribution v2.8.1+incompatible
|
github.com/docker/distribution v2.8.1+incompatible
|
||||||
github.com/docker/docker v20.10.22+incompatible
|
github.com/docker/docker v23.0.3+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/onsi/ginkgo v1.16.5
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.24.2
|
github.com/onsi/gomega v1.27.6
|
||||||
github.com/prometheus/client_golang v1.14.0
|
github.com/prometheus/client_golang v1.14.0
|
||||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.7.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.14.0
|
github.com/spf13/viper v1.15.0
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.2
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/net v0.9.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
@ -31,13 +31,13 @@ require (
|
||||||
github.com/fatih/color v1.13.0 // indirect
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.6 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
|
|
@ -45,25 +45,23 @@ require (
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/spf13/afero v1.9.2 // indirect
|
github.com/spf13/afero v1.9.3 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/stretchr/objx v0.5.0 // indirect
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
github.com/subosito/gotenv v1.4.1 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
golang.org/x/text v0.6.0
|
golang.org/x/text v0.9.0
|
||||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
|
golang.org/x/time v0.1.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gotest.tools/v3 v3.0.3 // indirect
|
gotest.tools/v3 v3.0.3 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containrrr/watchtower/internal/util"
|
"github.com/containrrr/watchtower/internal/util"
|
||||||
"github.com/containrrr/watchtower/pkg/container"
|
"github.com/containrrr/watchtower/pkg/container"
|
||||||
|
|
@ -260,10 +259,6 @@ func UpdateImplicitRestart(containers []container.Container) {
|
||||||
// container marked for restart
|
// container marked for restart
|
||||||
func linkedContainerMarkedForRestart(links []string, containers []container.Container) string {
|
func linkedContainerMarkedForRestart(links []string, containers []container.Container) string {
|
||||||
for _, linkName := range links {
|
for _, linkName := range links {
|
||||||
// Since the container names need to start with '/', let's prepend it if it's missing
|
|
||||||
if !strings.HasPrefix(linkName, "/") {
|
|
||||||
linkName = "/" + linkName
|
|
||||||
}
|
|
||||||
for _, candidate := range containers {
|
for _, candidate := range containers {
|
||||||
if candidate.Name() == linkName && candidate.ToRestart() {
|
if candidate.Name() == linkName && candidate.ToRestart() {
|
||||||
return linkName
|
return linkName
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ func (client dockerClient) StartContainer(c Container) (t.ContainerID, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client dockerClient) doStartContainer(bg context.Context, c Container, creation container.ContainerCreateCreatedBody) error {
|
func (client dockerClient) doStartContainer(bg context.Context, c Container, creation container.CreateResponse) error {
|
||||||
name := c.Name()
|
name := c.Name()
|
||||||
|
|
||||||
log.Debugf("Starting container %s (%s)", name, t.ContainerID(creation.ID).ShortID())
|
log.Debugf("Starting container %s (%s)", name, t.ContainerID(creation.ID).ShortID())
|
||||||
|
|
@ -280,7 +280,7 @@ func (client dockerClient) RenameContainer(c Container, newName string) error {
|
||||||
func (client dockerClient) IsContainerStale(container Container) (stale bool, latestImage t.ImageID, err error) {
|
func (client dockerClient) IsContainerStale(container Container) (stale bool, latestImage t.ImageID, err error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
if !client.PullImages {
|
if !client.PullImages || container.IsNoPull() {
|
||||||
log.Debugf("Skipping image pull.")
|
log.Debugf("Skipping image pull.")
|
||||||
} else if err := client.PullImage(ctx, container); err != nil {
|
} else if err := client.PullImage(ctx, container); err != nil {
|
||||||
return false, container.SafeImageID(), err
|
return false, container.SafeImageID(), err
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,22 @@ func (c Container) IsMonitorOnly() bool {
|
||||||
return parsedBool
|
return parsedBool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNoPull returns the value of the no-pull label. If the label is not set
|
||||||
|
// then false is returned.
|
||||||
|
func (c Container) IsNoPull() bool {
|
||||||
|
rawBool, ok := c.getLabelValue(noPullLabel)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedBool, err := strconv.ParseBool(rawBool)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedBool
|
||||||
|
}
|
||||||
|
|
||||||
// Scope returns the value of the scope UID label and if the label
|
// Scope returns the value of the scope UID label and if the label
|
||||||
// was set.
|
// was set.
|
||||||
func (c Container) Scope() (string, bool) {
|
func (c Container) Scope() (string, bool) {
|
||||||
|
|
@ -144,7 +160,14 @@ func (c Container) Links() []string {
|
||||||
dependsOnLabelValue := c.getLabelValueOrEmpty(dependsOnLabel)
|
dependsOnLabelValue := c.getLabelValueOrEmpty(dependsOnLabel)
|
||||||
|
|
||||||
if dependsOnLabelValue != "" {
|
if dependsOnLabelValue != "" {
|
||||||
links := strings.Split(dependsOnLabelValue, ",")
|
for _, link := range strings.Split(dependsOnLabelValue, ",") {
|
||||||
|
// Since the container names need to start with '/', let's prepend it if it's missing
|
||||||
|
if !strings.HasPrefix(link, "/") {
|
||||||
|
link = "/" + link
|
||||||
|
}
|
||||||
|
links = append(links, link)
|
||||||
|
}
|
||||||
|
|
||||||
return links
|
return links
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,14 +178,21 @@ var _ = Describe("the container", func() {
|
||||||
"com.centurylinklabs.watchtower.depends-on": "postgres",
|
"com.centurylinklabs.watchtower.depends-on": "postgres",
|
||||||
}))
|
}))
|
||||||
links := c.Links()
|
links := c.Links()
|
||||||
Expect(links).To(SatisfyAll(ContainElement("postgres"), HaveLen(1)))
|
Expect(links).To(SatisfyAll(ContainElement("/postgres"), HaveLen(1)))
|
||||||
})
|
})
|
||||||
It("should fetch depending containers if there are many", func() {
|
It("should fetch depending containers if there are many", func() {
|
||||||
c = MockContainer(WithLabels(map[string]string{
|
c = MockContainer(WithLabels(map[string]string{
|
||||||
"com.centurylinklabs.watchtower.depends-on": "postgres,redis",
|
"com.centurylinklabs.watchtower.depends-on": "postgres,redis",
|
||||||
}))
|
}))
|
||||||
links := c.Links()
|
links := c.Links()
|
||||||
Expect(links).To(SatisfyAll(ContainElement("postgres"), ContainElement("redis"), HaveLen(2)))
|
Expect(links).To(SatisfyAll(ContainElement("/postgres"), ContainElement("/redis"), HaveLen(2)))
|
||||||
|
})
|
||||||
|
It("should only add slashes to names when they are missing", func() {
|
||||||
|
c = MockContainer(WithLabels(map[string]string{
|
||||||
|
"com.centurylinklabs.watchtower.depends-on": "/postgres,redis",
|
||||||
|
}))
|
||||||
|
links := c.Links()
|
||||||
|
Expect(links).To(SatisfyAll(ContainElement("/postgres"), ContainElement("/redis")))
|
||||||
})
|
})
|
||||||
It("should fetch depending containers if label is blank", func() {
|
It("should fetch depending containers if label is blank", func() {
|
||||||
c = MockContainer(WithLabels(map[string]string{
|
c = MockContainer(WithLabels(map[string]string{
|
||||||
|
|
@ -207,6 +214,39 @@ var _ = Describe("the container", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
When("checking no-pull label", func() {
|
||||||
|
When("no-pull label is true", func() {
|
||||||
|
c := MockContainer(WithLabels(map[string]string{
|
||||||
|
"com.centurylinklabs.watchtower.no-pull": "true",
|
||||||
|
}))
|
||||||
|
It("should return true", func() {
|
||||||
|
Expect(c.IsNoPull()).To(Equal(true))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
When("no-pull label is false", func() {
|
||||||
|
c := MockContainer(WithLabels(map[string]string{
|
||||||
|
"com.centurylinklabs.watchtower.no-pull": "false",
|
||||||
|
}))
|
||||||
|
It("should return false", func() {
|
||||||
|
Expect(c.IsNoPull()).To(Equal(false))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
When("no-pull label is set to an invalid value", func() {
|
||||||
|
c := MockContainer(WithLabels(map[string]string{
|
||||||
|
"com.centurylinklabs.watchtower.no-pull": "maybe",
|
||||||
|
}))
|
||||||
|
It("should return false", func() {
|
||||||
|
Expect(c.IsNoPull()).To(Equal(false))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
When("no-pull label is unset", func() {
|
||||||
|
c = MockContainer(WithLabels(map[string]string{}))
|
||||||
|
It("should return false", func() {
|
||||||
|
Expect(c.IsNoPull()).To(Equal(false))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
When("there is a pre or post update timeout", func() {
|
When("there is a pre or post update timeout", func() {
|
||||||
It("should return minute values", func() {
|
It("should return minute values", func() {
|
||||||
c = MockContainer(WithLabels(map[string]string{
|
c = MockContainer(WithLabels(map[string]string{
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
package container
|
package container
|
||||||
|
|
||||||
const (
|
const (
|
||||||
watchtowerLabel = "com.centurylinklabs.watchtower"
|
watchtowerLabel = "com.centurylinklabs.watchtower"
|
||||||
signalLabel = "com.centurylinklabs.watchtower.stop-signal"
|
signalLabel = "com.centurylinklabs.watchtower.stop-signal"
|
||||||
enableLabel = "com.centurylinklabs.watchtower.enable"
|
enableLabel = "com.centurylinklabs.watchtower.enable"
|
||||||
monitorOnlyLabel = "com.centurylinklabs.watchtower.monitor-only"
|
monitorOnlyLabel = "com.centurylinklabs.watchtower.monitor-only"
|
||||||
dependsOnLabel = "com.centurylinklabs.watchtower.depends-on"
|
noPullLabel = "com.centurylinklabs.watchtower.no-pull"
|
||||||
zodiacLabel = "com.centurylinklabs.zodiac.original-image"
|
dependsOnLabel = "com.centurylinklabs.watchtower.depends-on"
|
||||||
scope = "com.centurylinklabs.watchtower.scope"
|
zodiacLabel = "com.centurylinklabs.zodiac.original-image"
|
||||||
preCheckLabel = "com.centurylinklabs.watchtower.lifecycle.pre-check"
|
scope = "com.centurylinklabs.watchtower.scope"
|
||||||
postCheckLabel = "com.centurylinklabs.watchtower.lifecycle.post-check"
|
preCheckLabel = "com.centurylinklabs.watchtower.lifecycle.pre-check"
|
||||||
preUpdateLabel = "com.centurylinklabs.watchtower.lifecycle.pre-update"
|
postCheckLabel = "com.centurylinklabs.watchtower.lifecycle.post-check"
|
||||||
postUpdateLabel = "com.centurylinklabs.watchtower.lifecycle.post-update"
|
preUpdateLabel = "com.centurylinklabs.watchtower.lifecycle.pre-update"
|
||||||
preUpdateTimeoutLabel = "com.centurylinklabs.watchtower.lifecycle.pre-update-timeout"
|
postUpdateLabel = "com.centurylinklabs.watchtower.lifecycle.post-update"
|
||||||
|
preUpdateTimeoutLabel = "com.centurylinklabs.watchtower.lifecycle.pre-update-timeout"
|
||||||
postUpdateTimeoutLabel = "com.centurylinklabs.watchtower.lifecycle.post-update-timeout"
|
postUpdateTimeoutLabel = "com.centurylinklabs.watchtower.lifecycle.post-update-timeout"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,6 @@ func ListContainersHandler(statuses ...string) http.HandlerFunc {
|
||||||
bytes, err := filterArgs.MarshalJSON()
|
bytes, err := filterArgs.MarshalJSON()
|
||||||
O.ExpectWithOffset(1, err).ShouldNot(O.HaveOccurred())
|
O.ExpectWithOffset(1, err).ShouldNot(O.HaveOccurred())
|
||||||
query := url.Values{
|
query := url.Values{
|
||||||
"limit": []string{"0"},
|
|
||||||
"filters": []string{string(bytes)},
|
"filters": []string{string(bytes)},
|
||||||
}
|
}
|
||||||
return ghttp.CombineHandlers(
|
return ghttp.CombineHandlers(
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,6 @@ var commonTemplates = map[string]string{
|
||||||
no containers matched filter
|
no containers matched filter
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}`,
|
{{- end -}}`,
|
||||||
}
|
|
||||||
|
|
||||||
|
`json.v1`: `{{ . | ToJSON }}`,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ func (e *emailTypeNotifier) GetURL(c *cobra.Command) (string, error) {
|
||||||
UseHTML: false,
|
UseHTML: false,
|
||||||
Encryption: shoutrrrSmtp.EncMethods.Auto,
|
Encryption: shoutrrrSmtp.EncMethods.Auto,
|
||||||
Auth: shoutrrrSmtp.AuthTypes.None,
|
Auth: shoutrrrSmtp.AuthTypes.None,
|
||||||
|
ClientHost: "localhost",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(e.User) > 0 {
|
if len(e.User) > 0 {
|
||||||
|
|
|
||||||
71
pkg/notifications/json.go
Normal file
71
pkg/notifications/json.go
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
package notifications
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
t "github.com/containrrr/watchtower/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type jsonMap = map[string]interface{}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler
|
||||||
|
func (d Data) MarshalJSON() ([]byte, error) {
|
||||||
|
var entries = make([]jsonMap, len(d.Entries))
|
||||||
|
for i, entry := range d.Entries {
|
||||||
|
entries[i] = jsonMap{
|
||||||
|
`level`: entry.Level,
|
||||||
|
`message`: entry.Message,
|
||||||
|
`data`: entry.Data,
|
||||||
|
`time`: entry.Time,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var report jsonMap
|
||||||
|
if d.Report != nil {
|
||||||
|
report = jsonMap{
|
||||||
|
`scanned`: marshalReports(d.Report.Scanned()),
|
||||||
|
`updated`: marshalReports(d.Report.Updated()),
|
||||||
|
`failed`: marshalReports(d.Report.Failed()),
|
||||||
|
`skipped`: marshalReports(d.Report.Skipped()),
|
||||||
|
`stale`: marshalReports(d.Report.Stale()),
|
||||||
|
`fresh`: marshalReports(d.Report.Fresh()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(jsonMap{
|
||||||
|
`report`: report,
|
||||||
|
`title`: d.Title,
|
||||||
|
`host`: d.Host,
|
||||||
|
`entries`: entries,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalReports(reports []t.ContainerReport) []jsonMap {
|
||||||
|
jsonReports := make([]jsonMap, len(reports))
|
||||||
|
for i, report := range reports {
|
||||||
|
jsonReports[i] = jsonMap{
|
||||||
|
`id`: report.ID().ShortID(),
|
||||||
|
`name`: report.Name(),
|
||||||
|
`currentImageId`: report.CurrentImageID().ShortID(),
|
||||||
|
`latestImageId`: report.LatestImageID().ShortID(),
|
||||||
|
`imageName`: report.ImageName(),
|
||||||
|
`state`: report.State(),
|
||||||
|
}
|
||||||
|
if errorMessage := report.Error(); errorMessage != "" {
|
||||||
|
jsonReports[i][`error`] = errorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonReports
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ json.Marshaler = &Data{}
|
||||||
|
|
||||||
|
func toJSON(v interface{}) string {
|
||||||
|
var bytes []byte
|
||||||
|
var err error
|
||||||
|
if bytes, err = json.MarshalIndent(v, "", " "); err != nil {
|
||||||
|
LocalLog.Errorf("failed to marshal JSON in notification template: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(bytes)
|
||||||
|
}
|
||||||
118
pkg/notifications/json_test.go
Normal file
118
pkg/notifications/json_test.go
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
package notifications
|
||||||
|
|
||||||
|
import (
|
||||||
|
s "github.com/containrrr/watchtower/pkg/session"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("JSON template", func() {
|
||||||
|
When("using report templates", func() {
|
||||||
|
When("JSON template is used", func() {
|
||||||
|
It("should format the messages to the expected format", func() {
|
||||||
|
expected := `{
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"data": null,
|
||||||
|
"level": "info",
|
||||||
|
"message": "foo Bar",
|
||||||
|
"time": "0001-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"host": "Mock",
|
||||||
|
"report": {
|
||||||
|
"failed": [
|
||||||
|
{
|
||||||
|
"currentImageId": "01d210000000",
|
||||||
|
"error": "accidentally the whole container",
|
||||||
|
"id": "c79210000000",
|
||||||
|
"imageName": "mock/fail1:latest",
|
||||||
|
"latestImageId": "d0a210000000",
|
||||||
|
"name": "fail1",
|
||||||
|
"state": "Failed"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fresh": [
|
||||||
|
{
|
||||||
|
"currentImageId": "01d310000000",
|
||||||
|
"id": "c79310000000",
|
||||||
|
"imageName": "mock/frsh1:latest",
|
||||||
|
"latestImageId": "01d310000000",
|
||||||
|
"name": "frsh1",
|
||||||
|
"state": "Fresh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scanned": [
|
||||||
|
{
|
||||||
|
"currentImageId": "01d110000000",
|
||||||
|
"id": "c79110000000",
|
||||||
|
"imageName": "mock/updt1:latest",
|
||||||
|
"latestImageId": "d0a110000000",
|
||||||
|
"name": "updt1",
|
||||||
|
"state": "Updated"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"currentImageId": "01d120000000",
|
||||||
|
"id": "c79120000000",
|
||||||
|
"imageName": "mock/updt2:latest",
|
||||||
|
"latestImageId": "d0a120000000",
|
||||||
|
"name": "updt2",
|
||||||
|
"state": "Updated"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"currentImageId": "01d210000000",
|
||||||
|
"error": "accidentally the whole container",
|
||||||
|
"id": "c79210000000",
|
||||||
|
"imageName": "mock/fail1:latest",
|
||||||
|
"latestImageId": "d0a210000000",
|
||||||
|
"name": "fail1",
|
||||||
|
"state": "Failed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"currentImageId": "01d310000000",
|
||||||
|
"id": "c79310000000",
|
||||||
|
"imageName": "mock/frsh1:latest",
|
||||||
|
"latestImageId": "01d310000000",
|
||||||
|
"name": "frsh1",
|
||||||
|
"state": "Fresh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"skipped": [
|
||||||
|
{
|
||||||
|
"currentImageId": "01d410000000",
|
||||||
|
"error": "unpossible",
|
||||||
|
"id": "c79410000000",
|
||||||
|
"imageName": "mock/skip1:latest",
|
||||||
|
"latestImageId": "01d410000000",
|
||||||
|
"name": "skip1",
|
||||||
|
"state": "Skipped"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stale": [],
|
||||||
|
"updated": [
|
||||||
|
{
|
||||||
|
"currentImageId": "01d110000000",
|
||||||
|
"id": "c79110000000",
|
||||||
|
"imageName": "mock/updt1:latest",
|
||||||
|
"latestImageId": "d0a110000000",
|
||||||
|
"name": "updt1",
|
||||||
|
"state": "Updated"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"currentImageId": "01d120000000",
|
||||||
|
"id": "c79120000000",
|
||||||
|
"imageName": "mock/updt2:latest",
|
||||||
|
"latestImageId": "d0a120000000",
|
||||||
|
"name": "updt2",
|
||||||
|
"state": "Updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"title": "Watchtower updates on Mock"
|
||||||
|
}`
|
||||||
|
data := mockDataFromStates(s.UpdatedState, s.FreshState, s.FailedState, s.SkippedState, s.UpdatedState)
|
||||||
|
Expect(getTemplatedResult(`json.v1`, false, data)).To(MatchJSON(expected))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
19
pkg/notifications/model.go
Normal file
19
pkg/notifications/model.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package notifications
|
||||||
|
|
||||||
|
import (
|
||||||
|
t "github.com/containrrr/watchtower/pkg/types"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StaticData is the part of the notification template data model set upon initialization
|
||||||
|
type StaticData struct {
|
||||||
|
Title string
|
||||||
|
Host string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data is the notification template data model
|
||||||
|
type Data struct {
|
||||||
|
StaticData
|
||||||
|
Entries []*log.Entry
|
||||||
|
Report t.Report
|
||||||
|
}
|
||||||
|
|
@ -210,6 +210,7 @@ func getShoutrrrTemplate(tplString string, legacy bool) (tpl *template.Template,
|
||||||
funcs := template.FuncMap{
|
funcs := template.FuncMap{
|
||||||
"ToUpper": strings.ToUpper,
|
"ToUpper": strings.ToUpper,
|
||||||
"ToLower": strings.ToLower,
|
"ToLower": strings.ToLower,
|
||||||
|
"ToJSON": toJSON,
|
||||||
"Title": cases.Title(language.AmericanEnglish).String,
|
"Title": cases.Title(language.AmericanEnglish).String,
|
||||||
}
|
}
|
||||||
tplBase := template.New("").Funcs(funcs)
|
tplBase := template.New("").Funcs(funcs)
|
||||||
|
|
@ -240,16 +241,3 @@ func getShoutrrrTemplate(tplString string, legacy bool) (tpl *template.Template,
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticData is the part of the notification template data model set upon initialization
|
|
||||||
type StaticData struct {
|
|
||||||
Title string
|
|
||||||
Host string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data is the notification template data model
|
|
||||||
type Data struct {
|
|
||||||
StaticData
|
|
||||||
Entries []*log.Entry
|
|
||||||
Report t.Report
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,8 @@ func GetBearerHeader(challenge string, imageRef ref.Named, registryAuth string)
|
||||||
|
|
||||||
if registryAuth != "" {
|
if registryAuth != "" {
|
||||||
logrus.Debug("Credentials found.")
|
logrus.Debug("Credentials found.")
|
||||||
logrus.Tracef("Credentials: %v", registryAuth)
|
// CREDENTIAL: Uncomment to log registry credentials
|
||||||
|
// logrus.Tracef("Credentials: %v", registryAuth)
|
||||||
r.Header.Add("Authorization", fmt.Sprintf("Basic %s", registryAuth))
|
r.Header.Add("Authorization", fmt.Sprintf("Basic %s", registryAuth))
|
||||||
} else {
|
} else {
|
||||||
logrus.Debug("No credentials found.")
|
logrus.Debug("No credentials found.")
|
||||||
|
|
@ -120,10 +121,9 @@ func GetAuthURL(challenge string, imageRef ref.Named) (*url.URL, error) {
|
||||||
|
|
||||||
for _, pair := range pairs {
|
for _, pair := range pairs {
|
||||||
trimmed := strings.Trim(pair, " ")
|
trimmed := strings.Trim(pair, " ")
|
||||||
kv := strings.Split(trimmed, "=")
|
if key, val, ok := strings.Cut(trimmed, "="); ok {
|
||||||
key := kv[0]
|
values[key] = strings.Trim(val, `"`)
|
||||||
val := strings.Trim(kv[1], "\"")
|
}
|
||||||
values[key] = val
|
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"realm": values["realm"],
|
"realm": values["realm"],
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||||
"github.com/containrrr/watchtower/pkg/registry/auth"
|
"github.com/containrrr/watchtower/pkg/registry/auth"
|
||||||
|
|
||||||
wtTypes "github.com/containrrr/watchtower/pkg/types"
|
wtTypes "github.com/containrrr/watchtower/pkg/types"
|
||||||
ref "github.com/docker/distribution/reference"
|
ref "github.com/docker/distribution/reference"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
|
|
@ -109,6 +110,18 @@ var _ = Describe("the auth module", func() {
|
||||||
Expect(getScopeFromImageAuthURL("ghcr.io/containrrr/watchtower")).To(Equal("containrrr/watchtower"))
|
Expect(getScopeFromImageAuthURL("ghcr.io/containrrr/watchtower")).To(Equal("containrrr/watchtower"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
It("should not crash when an empty field is recieved", func() {
|
||||||
|
input := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull",`
|
||||||
|
res, err := auth.GetAuthURL(input, "containrrr/watchtower")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(res).NotTo(BeNil())
|
||||||
|
})
|
||||||
|
It("should not crash when a field without a value is recieved", func() {
|
||||||
|
input := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull",valuelesskey`
|
||||||
|
res, err := auth.GetAuthURL(input, "containrrr/watchtower")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(res).NotTo(BeNil())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("GetChallengeURL", func() {
|
Describe("GetChallengeURL", func() {
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,16 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/containrrr/watchtower/internal/meta"
|
"github.com/containrrr/watchtower/internal/meta"
|
||||||
"github.com/containrrr/watchtower/pkg/registry/auth"
|
"github.com/containrrr/watchtower/pkg/registry/auth"
|
||||||
"github.com/containrrr/watchtower/pkg/registry/manifest"
|
"github.com/containrrr/watchtower/pkg/registry/manifest"
|
||||||
"github.com/containrrr/watchtower/pkg/types"
|
"github.com/containrrr/watchtower/pkg/types"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContentDigestHeader is the key for the key-value pair containing the digest header
|
// ContentDigestHeader is the key for the key-value pair containing the digest header
|
||||||
|
|
@ -25,7 +26,7 @@ func CompareDigest(container types.Container, registryAuth string) (bool, error)
|
||||||
if !container.HasImageInfo() {
|
if !container.HasImageInfo() {
|
||||||
return false, errors.New("container image info missing")
|
return false, errors.New("container image info missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
var digest string
|
var digest string
|
||||||
|
|
||||||
registryAuth = TransformAuth(registryAuth)
|
registryAuth = TransformAuth(registryAuth)
|
||||||
|
|
@ -93,16 +94,18 @@ func GetDigest(url string, token string) (string, error) {
|
||||||
req, _ := http.NewRequest("HEAD", url, nil)
|
req, _ := http.NewRequest("HEAD", url, nil)
|
||||||
req.Header.Set("User-Agent", meta.UserAgent)
|
req.Header.Set("User-Agent", meta.UserAgent)
|
||||||
|
|
||||||
if token != "" {
|
if token == "" {
|
||||||
logrus.WithField("token", token).Trace("Setting request token")
|
|
||||||
} else {
|
|
||||||
return "", errors.New("could not fetch token")
|
return "", errors.New("could not fetch token")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CREDENTIAL: Uncomment to log the request token
|
||||||
|
// logrus.WithField("token", token).Trace("Setting request token")
|
||||||
|
|
||||||
req.Header.Add("Authorization", token)
|
req.Header.Add("Authorization", token)
|
||||||
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json")
|
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json")
|
||||||
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.list.v2+json")
|
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.list.v2+json")
|
||||||
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v1+json")
|
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v1+json")
|
||||||
|
req.Header.Add("Accept", "application/vnd.oci.image.index.v1+json")
|
||||||
|
|
||||||
logrus.WithField("url", url).Debug("Doing a HEAD request to fetch a digest")
|
logrus.WithField("url", url).Debug("Doing a HEAD request to fetch a digest")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ func GetPullOptions(imageName string) (types.ImagePullOptions, error) {
|
||||||
if auth == "" {
|
if auth == "" {
|
||||||
return types.ImagePullOptions{}, nil
|
return types.ImagePullOptions{}, nil
|
||||||
}
|
}
|
||||||
log.Tracef("Got auth value: %s", auth)
|
|
||||||
|
// CREDENTIAL: Uncomment to log docker config auth
|
||||||
|
// log.Tracef("Got auth value: %s", auth)
|
||||||
|
|
||||||
return types.ImagePullOptions{
|
return types.ImagePullOptions{
|
||||||
RegistryAuth: auth,
|
RegistryAuth: auth,
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,11 @@ func EncodedEnvAuth() (string, error) {
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Loaded auth credentials for registry user %s from environment", auth.Username)
|
log.Debugf("Loaded auth credentials for registry user %s from environment", auth.Username)
|
||||||
log.Tracef("Using auth password %s", auth.Password)
|
// CREDENTIAL: Uncomment to log REPO_PASS environment variable
|
||||||
|
// log.Tracef("Using auth password %s", auth.Password)
|
||||||
|
|
||||||
return EncodeAuth(auth)
|
return EncodeAuth(auth)
|
||||||
}
|
}
|
||||||
return "", errors.New("registry auth environment variables (REPO_USER, REPO_PASS) not set")
|
return "", errors.New("registry auth environment variables (REPO_USER, REPO_PASS) not set")
|
||||||
|
|
@ -71,7 +74,8 @@ func EncodedConfigAuth(imageRef string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
log.Debugf("Loaded auth credentials for user %s, on registry %s, from file %s", auth.Username, server, configFile.Filename)
|
log.Debugf("Loaded auth credentials for user %s, on registry %s, from file %s", auth.Username, server, configFile.Filename)
|
||||||
log.Tracef("Using auth password %s", auth.Password)
|
// CREDENTIAL: Uncomment to log docker config password
|
||||||
|
// log.Tracef("Using auth password %s", auth.Password)
|
||||||
return EncodeAuth(auth)
|
return EncodeAuth(auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue