mirror of
https://github.com/containrrr/watchtower.git
synced 2026-02-23 15:44:07 +01:00
Consolidated all post-fork updates including dependency bumps and workflow changes
This commit is contained in:
parent
2abaa47fd3
commit
6b62d53797
100 changed files with 1503 additions and 1264 deletions
|
|
@ -1,7 +1,7 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/metrics"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/metrics"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@ package metrics_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/api"
|
||||
metricsAPI "github.com/containrrr/watchtower/pkg/api/metrics"
|
||||
"github.com/containrrr/watchtower/pkg/metrics"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/nicholas-fedor/watchtower/pkg/api"
|
||||
metricsAPI "github.com/nicholas-fedor/watchtower/pkg/api/metrics"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -36,7 +36,7 @@ func getWithToken(handler http.Handler) map[string]string {
|
|||
handler.ServeHTTP(respWriter, req)
|
||||
|
||||
res := respWriter.Result()
|
||||
body, _ := ioutil.ReadAll(res.Body)
|
||||
body, _ := io.ReadAll(res.Body)
|
||||
|
||||
for _, line := range strings.Split(string(body), "\n") {
|
||||
if len(line) < 1 || line[0] == '#' {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
var dockerContainerPattern = regexp.MustCompile(`[0-9]+:.*:/docker/([a-f|0-9]{64})`)
|
||||
|
|
|
|||
|
|
@ -3,21 +3,21 @@ package container
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/registry"
|
||||
"github.com/containrrr/watchtower/pkg/registry/digest"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
sdkClient "github.com/docker/docker/client"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/digest"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
const defaultStopSignal = "SIGTERM"
|
||||
|
|
@ -57,7 +57,6 @@ func NewClient(opts ClientOptions) Client {
|
|||
|
||||
// ClientOptions contains the options for how the docker client wrapper should behave
|
||||
type ClientOptions struct {
|
||||
PullImages bool
|
||||
RemoveVolumes bool
|
||||
IncludeStopped bool
|
||||
ReviveStopped bool
|
||||
|
|
@ -110,7 +109,7 @@ func (client dockerClient) ListContainers(fn t.Filter) ([]t.Container, error) {
|
|||
filter := client.createListFilter()
|
||||
containers, err := client.api.ContainerList(
|
||||
bg,
|
||||
types.ContainerListOptions{
|
||||
container.ListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
|
||||
|
|
@ -207,7 +206,7 @@ func (client dockerClient) StopContainer(c t.Container, timeout time.Duration) e
|
|||
} else {
|
||||
log.Debugf("Removing container %s", shortID)
|
||||
|
||||
if err := client.api.ContainerRemove(bg, idStr, types.ContainerRemoveOptions{Force: true, RemoveVolumes: client.RemoveVolumes}); err != nil {
|
||||
if err := client.api.ContainerRemove(bg, idStr, container.RemoveOptions{Force: true, RemoveVolumes: client.RemoveVolumes}); err != nil {
|
||||
if sdkClient.IsErrNotFound(err) {
|
||||
log.Debugf("Container %s not found, skipping removal.", shortID)
|
||||
return nil
|
||||
|
|
@ -304,7 +303,7 @@ func (client dockerClient) doStartContainer(bg context.Context, c t.Container, c
|
|||
name := c.Name()
|
||||
|
||||
log.Debugf("Starting container %s (%s)", name, t.ContainerID(creation.ID).ShortID())
|
||||
err := client.api.ContainerStart(bg, creation.ID, types.ContainerStartOptions{})
|
||||
err := client.api.ContainerStart(bg, creation.ID, container.StartOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -399,7 +398,7 @@ func (client dockerClient) PullImage(ctx context.Context, container t.Container)
|
|||
|
||||
defer response.Close()
|
||||
// the pull request will be aborted prematurely unless the response is read
|
||||
if _, err = ioutil.ReadAll(response); err != nil {
|
||||
if _, err = io.ReadAll(response); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
|
@ -412,7 +411,7 @@ func (client dockerClient) RemoveImageByID(id t.ImageID) error {
|
|||
items, err := client.api.ImageRemove(
|
||||
context.Background(),
|
||||
string(id),
|
||||
types.ImageRemoveOptions{
|
||||
image.RemoveOptions{
|
||||
Force: true,
|
||||
})
|
||||
|
||||
|
|
@ -445,7 +444,7 @@ func (client dockerClient) ExecuteCommand(containerID t.ContainerID, command str
|
|||
clog := log.WithField("containerID", containerID)
|
||||
|
||||
// Create the exec
|
||||
execConfig := types.ExecConfig{
|
||||
execConfig := container.ExecOptions{
|
||||
Tty: true,
|
||||
Detach: false,
|
||||
Cmd: []string{"sh", "-c", command},
|
||||
|
|
@ -456,7 +455,7 @@ func (client dockerClient) ExecuteCommand(containerID t.ContainerID, command str
|
|||
return false, err
|
||||
}
|
||||
|
||||
response, attachErr := client.api.ContainerExecAttach(bg, exec.ID, types.ExecStartCheck{
|
||||
response, attachErr := client.api.ContainerExecAttach(bg, exec.ID, container.ExecStartOptions{
|
||||
Tty: true,
|
||||
Detach: false,
|
||||
})
|
||||
|
|
@ -465,7 +464,7 @@ func (client dockerClient) ExecuteCommand(containerID t.ContainerID, command str
|
|||
}
|
||||
|
||||
// Run the exec
|
||||
execStartCheck := types.ExecStartCheck{Detach: false, Tty: true}
|
||||
execStartCheck := container.ExecStartOptions{Detach: false, Tty: true}
|
||||
err = client.api.ContainerExecStart(bg, exec.ID, execStartCheck)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/internal/util"
|
||||
"github.com/containrrr/watchtower/pkg/container/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/filters"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
|
||||
"github.com/nicholas-fedor/watchtower/internal/util"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/container/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/filters"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
|
|
@ -70,7 +72,8 @@ var _ = Describe("the client", func() {
|
|||
It("should gracefully fail with a useful message", func() {
|
||||
c := dockerClient{}
|
||||
pinnedContainer := MockContainer(WithImageName("sha256:fa5269854a5e615e51a72b17ad3fd1e01268f278a6684c8ed3c5f0cdce3f230b"))
|
||||
c.PullImage(context.Background(), pinnedContainer)
|
||||
err := c.PullImage(context.Background(), pinnedContainer)
|
||||
Expect(err).To(MatchError(`container uses a pinned image, and cannot be updated by watchtower`))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -144,7 +147,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&mocks.Watchtower, &mocks.Running)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -158,7 +161,7 @@ var _ = Describe("the client", func() {
|
|||
filter := filters.FilterByNames([]string{"lollercoaster"}, filters.NoFilter)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
containers, err := client.ListContainers(filter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -171,11 +174,11 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&mocks.Watchtower, &mocks.Running)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
containers, err := client.ListContainers(filters.WatchtowerContainersFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(containers).To(ConsistOf(withContainerImageName(Equal("containrrr/watchtower:latest"))))
|
||||
Expect(containers).To(ConsistOf(withContainerImageName(Equal("nickfedor/watchtower:latest"))))
|
||||
})
|
||||
})
|
||||
When(`include stopped is enabled`, func() {
|
||||
|
|
@ -184,7 +187,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&mocks.Stopped, &mocks.Watchtower, &mocks.Running)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false, IncludeStopped: true},
|
||||
ClientOptions: ClientOptions{IncludeStopped: true},
|
||||
}
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -197,7 +200,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&mocks.Watchtower, &mocks.Running, &mocks.Restarting)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false, IncludeRestarting: true},
|
||||
ClientOptions: ClientOptions{IncludeRestarting: true},
|
||||
}
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -210,7 +213,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&mocks.Watchtower, &mocks.Running)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false, IncludeRestarting: false},
|
||||
ClientOptions: ClientOptions{IncludeRestarting: false},
|
||||
}
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -224,7 +227,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&consumerContainerRef)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
container, err := client.GetContainer(consumerContainerRef.ContainerID())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -238,7 +241,7 @@ var _ = Describe("the client", func() {
|
|||
mockServer.AppendHandlers(mocks.GetContainerHandlers(&consumerContainerRef)...)
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
container, err := client.GetContainer(consumerContainerRef.ContainerID())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -253,7 +256,7 @@ var _ = Describe("the client", func() {
|
|||
It("should include container id field", func() {
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false},
|
||||
ClientOptions: ClientOptions{},
|
||||
}
|
||||
|
||||
// Capture logrus output in buffer
|
||||
|
|
@ -269,7 +272,7 @@ var _ = Describe("the client", func() {
|
|||
// API.ContainerExecCreate
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("POST", HaveSuffix("containers/%v/exec", containerID)),
|
||||
ghttp.VerifyJSONRepresenting(types.ExecConfig{
|
||||
ghttp.VerifyJSONRepresenting(container.ExecOptions{
|
||||
User: user,
|
||||
Detach: false,
|
||||
Tty: true,
|
||||
|
|
@ -284,7 +287,7 @@ var _ = Describe("the client", func() {
|
|||
// API.ContainerExecStart
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("POST", HaveSuffix("exec/%v/start", execID)),
|
||||
ghttp.VerifyJSONRepresenting(types.ExecStartCheck{
|
||||
ghttp.VerifyJSONRepresenting(container.ExecStartOptions{
|
||||
Detach: false,
|
||||
Tty: true,
|
||||
}),
|
||||
|
|
@ -320,7 +323,7 @@ var _ = Describe("the client", func() {
|
|||
It(`should omit the container ID alias`, func() {
|
||||
client := dockerClient{
|
||||
api: docker,
|
||||
ClientOptions: ClientOptions{PullImages: false, IncludeRestarting: false},
|
||||
ClientOptions: ClientOptions{IncludeRestarting: false},
|
||||
}
|
||||
container := MockContainer(WithImageName("docker.io/prefix/imagename:latest"))
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containrrr/watchtower/internal/util"
|
||||
wt "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/internal/util"
|
||||
wt "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
|
@ -304,6 +304,29 @@ func (c Container) GetCreateConfig() *dockercontainer.Config {
|
|||
}
|
||||
}
|
||||
|
||||
// Clear HEALTHCHECK configuration (if default)
|
||||
if config.Healthcheck != nil && imageConfig.Healthcheck != nil {
|
||||
if util.SliceEqual(config.Healthcheck.Test, imageConfig.Healthcheck.Test) {
|
||||
config.Healthcheck.Test = nil
|
||||
}
|
||||
|
||||
if config.Healthcheck.Retries == imageConfig.Healthcheck.Retries {
|
||||
config.Healthcheck.Retries = 0
|
||||
}
|
||||
|
||||
if config.Healthcheck.Interval == imageConfig.Healthcheck.Interval {
|
||||
config.Healthcheck.Interval = 0
|
||||
}
|
||||
|
||||
if config.Healthcheck.Timeout == imageConfig.Healthcheck.Timeout {
|
||||
config.Healthcheck.Timeout = 0
|
||||
}
|
||||
|
||||
if config.Healthcheck.StartPeriod == imageConfig.Healthcheck.StartPeriod {
|
||||
config.Healthcheck.StartPeriod = 0
|
||||
}
|
||||
}
|
||||
|
||||
config.Env = util.SliceSubtract(config.Env, imageConfig.Env)
|
||||
|
||||
config.Labels = util.StringMapSubtract(config.Labels, imageConfig.Labels)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ func MockContainer(updates ...MockContainerUpdate) *Container {
|
|||
},
|
||||
}
|
||||
image := types.ImageInspect{
|
||||
ID: "image_id",
|
||||
ID: "image_id",
|
||||
Config: &dockerContainer.Config{},
|
||||
}
|
||||
|
||||
for _, update := range updates {
|
||||
|
|
@ -64,3 +65,15 @@ func WithContainerState(state types.ContainerState) MockContainerUpdate {
|
|||
cnt.State = &state
|
||||
}
|
||||
}
|
||||
|
||||
func WithHealthcheck(healthConfig dockerContainer.HealthConfig) MockContainerUpdate {
|
||||
return func(cnt *types.ContainerJSON, img *types.ImageInspect) {
|
||||
cnt.Config.Healthcheck = &healthConfig
|
||||
}
|
||||
}
|
||||
|
||||
func WithImageHealthcheck(healthConfig dockerContainer.HealthConfig) MockContainerUpdate {
|
||||
return func(cnt *types.ContainerJSON, img *types.ImageInspect) {
|
||||
img.Config.Healthcheck = &healthConfig
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
dc "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/go-connections/nat"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
|
@ -67,6 +68,93 @@ var _ = Describe("the container", func() {
|
|||
})
|
||||
})
|
||||
})
|
||||
Describe("GetCreateConfig", func() {
|
||||
When("container healthcheck config is equal to image config", func() {
|
||||
It("should return empty healthcheck values", func() {
|
||||
c := MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
}), WithImageHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{}))
|
||||
|
||||
c = MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
Timeout: 30,
|
||||
}), WithImageHealthcheck(dc.HealthConfig{
|
||||
Timeout: 30,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{}))
|
||||
|
||||
c = MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
StartPeriod: 30,
|
||||
}), WithImageHealthcheck(dc.HealthConfig{
|
||||
StartPeriod: 30,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{}))
|
||||
|
||||
c = MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
Retries: 30,
|
||||
}), WithImageHealthcheck(dc.HealthConfig{
|
||||
Retries: 30,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{}))
|
||||
})
|
||||
})
|
||||
When("container healthcheck config is different to image config", func() {
|
||||
It("should return the container healthcheck values", func() {
|
||||
c := MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
Interval: 30,
|
||||
Timeout: 30,
|
||||
StartPeriod: 10,
|
||||
Retries: 2,
|
||||
}), WithImageHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "10s"},
|
||||
Interval: 10,
|
||||
Timeout: 60,
|
||||
StartPeriod: 30,
|
||||
Retries: 10,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
Interval: 30,
|
||||
Timeout: 30,
|
||||
StartPeriod: 10,
|
||||
Retries: 2,
|
||||
}))
|
||||
})
|
||||
})
|
||||
When("container healthcheck config is empty", func() {
|
||||
It("should not panic", func() {
|
||||
c := MockContainer(WithImageHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "10s"},
|
||||
Interval: 10,
|
||||
Timeout: 60,
|
||||
StartPeriod: 30,
|
||||
Retries: 10,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(BeNil())
|
||||
})
|
||||
})
|
||||
When("container image healthcheck config is empty", func() {
|
||||
It("should not panic", func() {
|
||||
c := MockContainer(WithHealthcheck(dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
Interval: 30,
|
||||
Timeout: 30,
|
||||
StartPeriod: 10,
|
||||
Retries: 2,
|
||||
}))
|
||||
Expect(c.GetCreateConfig().Healthcheck).To(Equal(&dc.HealthConfig{
|
||||
Test: []string{"/usr/bin/sleep", "1s"},
|
||||
Interval: 30,
|
||||
Timeout: 30,
|
||||
StartPeriod: 10,
|
||||
Retries: 2,
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
When("asked for metadata", func() {
|
||||
var c *Container
|
||||
BeforeEach(func() {
|
||||
|
|
|
|||
|
|
@ -3,16 +3,18 @@ package mocks
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/onsi/ginkgo"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
i "github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
O "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/ghttp"
|
||||
|
|
@ -262,12 +264,12 @@ func RemoveImageHandler(imagesWithParents map[string][]string) http.HandlerFunc
|
|||
image := parts[len(parts)-1]
|
||||
|
||||
if parents, found := imagesWithParents[image]; found {
|
||||
items := []types.ImageDeleteResponseItem{
|
||||
items := []i.DeleteResponse{
|
||||
{Untagged: image},
|
||||
{Deleted: image},
|
||||
}
|
||||
for _, parent := range parents {
|
||||
items = append(items, types.ImageDeleteResponseItem{Deleted: parent})
|
||||
items = append(items, i.DeleteResponse{Deleted: parent})
|
||||
}
|
||||
ghttp.RespondWithJSONEncoded(http.StatusOK, items)(w, r)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
type imageRef struct {
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@
|
|||
"AppArmorProfile": "",
|
||||
"ExecIDs": null,
|
||||
"HostConfig": {
|
||||
"Binds": [
|
||||
"/var/run/docker.sock:/var/run/docker.sock"
|
||||
],
|
||||
"Binds": ["/var/run/docker.sock:/var/run/docker.sock"],
|
||||
"ContainerIDFile": "",
|
||||
"LogConfig": {
|
||||
"Type": "json-file",
|
||||
|
|
@ -67,10 +65,7 @@
|
|||
"UsernsMode": "",
|
||||
"ShmSize": 67108864,
|
||||
"Runtime": "runc",
|
||||
"ConsoleSize": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ConsoleSize": [0, 0],
|
||||
"Isolation": "",
|
||||
"CpuShares": 0,
|
||||
"Memory": 0,
|
||||
|
|
@ -155,12 +150,10 @@
|
|||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": null,
|
||||
"Image": "containrrr/watchtower:latest",
|
||||
"Image": "nickfedor/watchtower:latest",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/watchtower"
|
||||
],
|
||||
"Entrypoint": ["/watchtower"],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"com.centurylinklabs.watchtower": "true"
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@
|
|||
"AppArmorProfile": "",
|
||||
"ExecIDs": null,
|
||||
"HostConfig": {
|
||||
"Binds": [
|
||||
"/var/run/docker.sock:/var/run/docker.sock"
|
||||
],
|
||||
"Binds": ["/var/run/docker.sock:/var/run/docker.sock"],
|
||||
"ContainerIDFile": "",
|
||||
"LogConfig": {
|
||||
"Type": "json-file",
|
||||
|
|
@ -67,10 +65,7 @@
|
|||
"UsernsMode": "",
|
||||
"ShmSize": 67108864,
|
||||
"Runtime": "runc",
|
||||
"ConsoleSize": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ConsoleSize": [0, 0],
|
||||
"Isolation": "",
|
||||
"CpuShares": 0,
|
||||
"Memory": 0,
|
||||
|
|
@ -155,12 +150,10 @@
|
|||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": null,
|
||||
"Image": "containrrr/watchtower:latest",
|
||||
"Image": "nickfedor/watchtower:latest",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/watchtower"
|
||||
],
|
||||
"Entrypoint": ["/watchtower"],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"com.centurylinklabs.watchtower": "true"
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@
|
|||
"AppArmorProfile": "",
|
||||
"ExecIDs": null,
|
||||
"HostConfig": {
|
||||
"Binds": [
|
||||
"/var/run/docker.sock:/var/run/docker.sock"
|
||||
],
|
||||
"Binds": ["/var/run/docker.sock:/var/run/docker.sock"],
|
||||
"ContainerIDFile": "",
|
||||
"LogConfig": {
|
||||
"Type": "json-file",
|
||||
|
|
@ -67,10 +65,7 @@
|
|||
"UsernsMode": "",
|
||||
"ShmSize": 67108864,
|
||||
"Runtime": "runc",
|
||||
"ConsoleSize": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"ConsoleSize": [0, 0],
|
||||
"Isolation": "",
|
||||
"CpuShares": 0,
|
||||
"Memory": 0,
|
||||
|
|
@ -155,12 +150,10 @@
|
|||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": null,
|
||||
"Image": "containrrr/watchtower:latest",
|
||||
"Image": "nickfedor/watchtower:latest",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/watchtower"
|
||||
],
|
||||
"Entrypoint": ["/watchtower"],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"com.centurylinklabs.watchtower": "true"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
[
|
||||
{
|
||||
"Id": "ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65",
|
||||
"Names": [
|
||||
"/watchtower-stopped"
|
||||
],
|
||||
"Image": "containrrr/watchtower:latest",
|
||||
"Names": ["/watchtower-stopped"],
|
||||
"Image": "nickfedor/watchtower:latest",
|
||||
"ImageID": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa",
|
||||
"Command": "/watchtower",
|
||||
"Created": 1554925882,
|
||||
|
|
@ -49,10 +47,8 @@
|
|||
},
|
||||
{
|
||||
"Id": "3d88e0e3543281c747d88b27e246578b65ae8964ba86c7cd7522cf84e0978134",
|
||||
"Names": [
|
||||
"/watchtower-running"
|
||||
],
|
||||
"Image": "containrrr/watchtower:latest",
|
||||
"Names": ["/watchtower-running"],
|
||||
"Image": "nickfedor/watchtower:latest",
|
||||
"ImageID": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa",
|
||||
"Command": "/watchtower",
|
||||
"Created": 1554925882,
|
||||
|
|
@ -97,9 +93,7 @@
|
|||
},
|
||||
{
|
||||
"Id": "b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008",
|
||||
"Names": [
|
||||
"/portainer"
|
||||
],
|
||||
"Names": ["/portainer"],
|
||||
"Image": "portainer/portainer:latest",
|
||||
"ImageID": "sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd",
|
||||
"Command": "/portainer",
|
||||
|
|
@ -160,9 +154,7 @@
|
|||
},
|
||||
{
|
||||
"Id": "ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b67",
|
||||
"Names": [
|
||||
"/portainer"
|
||||
],
|
||||
"Names": ["/portainer"],
|
||||
"Image": "portainer/portainer:latest",
|
||||
"ImageID": "sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd",
|
||||
"Command": "/portainer",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"Id": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa",
|
||||
"RepoTags": [
|
||||
"containrrr/watchtower:latest"
|
||||
],
|
||||
"RepoTags": ["nickfedor/watchtower:latest"],
|
||||
"RepoDigests": [],
|
||||
"Parent": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447",
|
||||
"Comment": "",
|
||||
|
|
@ -21,18 +19,11 @@
|
|||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"#(nop) ",
|
||||
"ENTRYPOINT [\"/watchtower\"]"
|
||||
],
|
||||
"Cmd": ["/bin/sh", "-c", "#(nop) ", "ENTRYPOINT [\"/watchtower\"]"],
|
||||
"Image": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/watchtower"
|
||||
],
|
||||
"Entrypoint": ["/watchtower"],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"com.centurylinklabs.watchtower": "true"
|
||||
|
|
@ -57,9 +48,7 @@
|
|||
"Image": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/watchtower"
|
||||
],
|
||||
"Entrypoint": ["/watchtower"],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"com.centurylinklabs.watchtower": "true"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package container_test
|
||||
|
||||
import (
|
||||
wt "github.com/containrrr/watchtower/pkg/types"
|
||||
wt "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
// WatchtowerContainersFilter filters only watchtower containers
|
||||
|
|
@ -86,13 +86,14 @@ func FilterByDisabledLabel(baseFilter t.Filter) t.Filter {
|
|||
|
||||
// FilterByScope returns all containers that belongs to a specific scope
|
||||
func FilterByScope(scope string, baseFilter t.Filter) t.Filter {
|
||||
if scope == "" {
|
||||
return baseFilter
|
||||
}
|
||||
|
||||
return func(c t.FilterableContainer) bool {
|
||||
containerScope, ok := c.Scope()
|
||||
if ok && containerScope == scope {
|
||||
containerScope, containerHasScope := c.Scope()
|
||||
|
||||
if !containerHasScope || containerScope == "" {
|
||||
containerScope = "none"
|
||||
}
|
||||
|
||||
if containerScope == scope {
|
||||
return baseFilter(c)
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +153,13 @@ func BuildFilter(names []string, disableNames []string, enableLabel bool, scope
|
|||
filter = FilterByEnableLabel(filter)
|
||||
sb.WriteString("using enable label, ")
|
||||
}
|
||||
if scope != "" {
|
||||
|
||||
if scope == "none" {
|
||||
// If a scope has explicitly defined as "none", containers should only be considered
|
||||
// if they do not have a scope defined, or if it's explicitly set to "none".
|
||||
filter = FilterByScope(scope, filter)
|
||||
sb.WriteString(`without a scope, "`)
|
||||
} else if scope != "" {
|
||||
// If a scope has been defined, containers should only be considered
|
||||
// if the scope is specifically set.
|
||||
filter = FilterByScope(scope, filter)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package filters
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/container/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/container/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -111,6 +111,53 @@ func TestFilterByScope(t *testing.T) {
|
|||
container.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestFilterByNoneScope(t *testing.T) {
|
||||
scope := "none"
|
||||
|
||||
filter := FilterByScope(scope, NoFilter)
|
||||
assert.NotNil(t, filter)
|
||||
|
||||
container := new(mocks.FilterableContainer)
|
||||
container.On("Scope").Return("anyscope", true)
|
||||
assert.False(t, filter(container))
|
||||
container.AssertExpectations(t)
|
||||
|
||||
container = new(mocks.FilterableContainer)
|
||||
container.On("Scope").Return("", false)
|
||||
assert.True(t, filter(container))
|
||||
container.AssertExpectations(t)
|
||||
|
||||
container = new(mocks.FilterableContainer)
|
||||
container.On("Scope").Return("", true)
|
||||
assert.True(t, filter(container))
|
||||
container.AssertExpectations(t)
|
||||
|
||||
container = new(mocks.FilterableContainer)
|
||||
container.On("Scope").Return("none", true)
|
||||
assert.True(t, filter(container))
|
||||
container.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestBuildFilterNoneScope(t *testing.T) {
|
||||
filter, desc := BuildFilter(nil, nil, false, "none")
|
||||
|
||||
assert.Contains(t, desc, "without a scope")
|
||||
|
||||
scoped := new(mocks.FilterableContainer)
|
||||
scoped.On("Enabled").Return(false, false)
|
||||
scoped.On("Scope").Return("anyscope", true)
|
||||
|
||||
unscoped := new(mocks.FilterableContainer)
|
||||
unscoped.On("Enabled").Return(false, false)
|
||||
unscoped.On("Scope").Return("", false)
|
||||
|
||||
assert.False(t, filter(scoped))
|
||||
assert.True(t, filter(unscoped))
|
||||
|
||||
scoped.AssertExpectations(t)
|
||||
unscoped.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestFilterByDisabledLabel(t *testing.T) {
|
||||
filter := FilterByDisabledLabel(NoFilter)
|
||||
assert.NotNil(t, filter)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package lifecycle
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/container"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
shoutrrrSmtp "github.com/containrrr/shoutrrr/pkg/services/smtp"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
shoutrrrGotify "github.com/containrrr/shoutrrr/pkg/services/gotify"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package notifications
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
type jsonMap = map[string]interface{}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package notifications
|
||||
|
||||
import (
|
||||
s "github.com/containrrr/watchtower/pkg/session"
|
||||
s "github.com/nicholas-fedor/watchtower/pkg/session"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package notifications
|
||||
|
||||
import (
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net/url"
|
||||
|
||||
shoutrrrTeams "github.com/containrrr/shoutrrr/pkg/services/teams"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
ty "github.com/containrrr/watchtower/pkg/types"
|
||||
ty "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import (
|
|||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/cmd"
|
||||
"github.com/containrrr/watchtower/internal/flags"
|
||||
"github.com/containrrr/watchtower/pkg/notifications"
|
||||
"github.com/nicholas-fedor/watchtower/cmd"
|
||||
"github.com/nicholas-fedor/watchtower/internal/flags"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/notifications"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
type previewData struct {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package data
|
|||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
// State is the outcome of a container in a session report
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package data
|
||||
|
||||
import wt "github.com/containrrr/watchtower/pkg/types"
|
||||
import wt "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
|
||||
type containerStatus struct {
|
||||
containerID wt.ContainerID
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/notifications/preview/data"
|
||||
"github.com/containrrr/watchtower/pkg/notifications/templates"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/notifications/preview/data"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/notifications/templates"
|
||||
)
|
||||
|
||||
func Render(input string, states []data.State, loglevels []data.LogLevel) (string, error) {
|
||||
|
|
@ -15,7 +15,7 @@ func Render(input string, states []data.State, loglevels []data.LogLevel) (strin
|
|||
|
||||
tpl, err := template.New("").Funcs(templates.Funcs).Parse(input)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse template: %e", err)
|
||||
return "", fmt.Errorf("failed to parse %v", err)
|
||||
}
|
||||
|
||||
for _, state := range states {
|
||||
|
|
@ -29,7 +29,7 @@ func Render(input string, states []data.State, loglevels []data.LogLevel) (strin
|
|||
var buf strings.Builder
|
||||
err = tpl.Execute(&buf, data)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to execute template: %e", err)
|
||||
return "", fmt.Errorf("failed to execute template: %v", err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import (
|
|||
|
||||
"github.com/containrrr/shoutrrr"
|
||||
"github.com/containrrr/shoutrrr/pkg/types"
|
||||
"github.com/containrrr/watchtower/pkg/notifications/templates"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/notifications/templates"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ func (n *shoutrrrTypeNotifier) GetNames() []string {
|
|||
return names
|
||||
}
|
||||
|
||||
// GetNames returns a list of URLs for notification services that has been added
|
||||
// GetURLs returns a list of URLs for notification services that has been added
|
||||
func (n *shoutrrrTypeNotifier) GetURLs() []string {
|
||||
return n.Urls
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ func (n *shoutrrrTypeNotifier) AddLogHook() {
|
|||
n.receiving = true
|
||||
log.AddHook(n)
|
||||
|
||||
// Do the sending in a separate goroutine so we don't block the main process.
|
||||
// Do the sending in a separate goroutine, so we don't block the main process.
|
||||
go sendNotifications(n)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/containrrr/shoutrrr/pkg/types"
|
||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
"github.com/containrrr/watchtower/internal/flags"
|
||||
s "github.com/containrrr/watchtower/pkg/session"
|
||||
"github.com/nicholas-fedor/watchtower/internal/actions/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/internal/flags"
|
||||
s "github.com/nicholas-fedor/watchtower/pkg/session"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gbytes"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
shoutrrrDisco "github.com/containrrr/shoutrrr/pkg/services/discord"
|
||||
shoutrrrSlack "github.com/containrrr/shoutrrr/pkg/services/slack"
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
t "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/registry/helpers"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
ref "github.com/docker/distribution/reference"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/helpers"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
ref "github.com/distribution/reference"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/registry/auth"
|
||||
"github.com/nicholas-fedor/watchtower/internal/actions/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/auth"
|
||||
|
||||
wtTypes "github.com/containrrr/watchtower/pkg/types"
|
||||
ref "github.com/docker/distribution/reference"
|
||||
ref "github.com/distribution/reference"
|
||||
wtTypes "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
@ -45,7 +45,7 @@ var _ = Describe("the auth module", func() {
|
|||
mockName := "mock-container"
|
||||
mockImage := "ghcr.io/k6io/operator:latest"
|
||||
mockCreated := time.Now()
|
||||
mockDigest := "ghcr.io/k6io/operator@sha256:d68e1e532088964195ad3a0a71526bc2f11a78de0def85629beb75e2265f0547"
|
||||
mockDigest := "ghcr.io/k6io/operator@sha256:d6d356ad6ec80e6765b99921babb8580ca0dee21c27abc3f0197c9441d83d680"
|
||||
|
||||
mockContainer := mocks.CreateMockContainerWithDigest(
|
||||
mockId,
|
||||
|
|
@ -68,13 +68,13 @@ var _ = Describe("the auth module", func() {
|
|||
Describe("GetAuthURL", func() {
|
||||
It("should create a valid auth url object based on the challenge header supplied", func() {
|
||||
challenge := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull"`
|
||||
imageRef, err := ref.ParseNormalizedNamed("containrrr/watchtower")
|
||||
imageRef, err := ref.ParseNormalizedNamed("nicholas-fedor/watchtower")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
expected := &url.URL{
|
||||
Host: "ghcr.io",
|
||||
Scheme: "https",
|
||||
Path: "/token",
|
||||
RawQuery: "scope=repository%3Acontainrrr%2Fwatchtower%3Apull&service=ghcr.io",
|
||||
RawQuery: "scope=repository%3Anicholas-fedor%2Fwatchtower%3Apull&service=ghcr.io",
|
||||
}
|
||||
|
||||
URL, err := auth.GetAuthURL(challenge, imageRef)
|
||||
|
|
@ -85,7 +85,7 @@ var _ = Describe("the auth module", func() {
|
|||
When("given an invalid challenge header", func() {
|
||||
It("should return an error", func() {
|
||||
challenge := `bearer realm="https://ghcr.io/token"`
|
||||
imageRef, err := ref.ParseNormalizedNamed("containrrr/watchtower")
|
||||
imageRef, err := ref.ParseNormalizedNamed("nicholas-fedor/watchtower")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
URL, err := auth.GetAuthURL(challenge, imageRef)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
|
@ -100,21 +100,17 @@ var _ = Describe("the auth module", func() {
|
|||
Expect(getScopeFromImageAuthURL("index.docker.io/registry")).To(Equal("library/registry"))
|
||||
})
|
||||
It("should not include vanity hosts\"", func() {
|
||||
Expect(getScopeFromImageAuthURL("docker.io/containrrr/watchtower")).To(Equal("containrrr/watchtower"))
|
||||
Expect(getScopeFromImageAuthURL("index.docker.io/containrrr/watchtower")).To(Equal("containrrr/watchtower"))
|
||||
})
|
||||
It("should not destroy three segment image names\"", func() {
|
||||
Expect(getScopeFromImageAuthURL("piksel/containrrr/watchtower")).To(Equal("piksel/containrrr/watchtower"))
|
||||
Expect(getScopeFromImageAuthURL("ghcr.io/piksel/containrrr/watchtower")).To(Equal("piksel/containrrr/watchtower"))
|
||||
})
|
||||
It("should not prepend library/ to image names if they're not on dockerhub", func() {
|
||||
Expect(getScopeFromImageAuthURL("ghcr.io/watchtower")).To(Equal("watchtower"))
|
||||
Expect(getScopeFromImageAuthURL("ghcr.io/containrrr/watchtower")).To(Equal("containrrr/watchtower"))
|
||||
Expect(getScopeFromImageAuthURL("docker.io/nickfedor/watchtower")).To(Equal("nickfedor/watchtower"))
|
||||
Expect(getScopeFromImageAuthURL("index.docker.io/nickfedor/watchtower")).To(Equal("nickfedor/watchtower"))
|
||||
})
|
||||
// It("should not prepend library/ to image names if they're not on dockerhub", func() {
|
||||
// Expect(getScopeFromImageAuthURL("ghcr.io/watchtower")).To(Equal("watchtower"))
|
||||
// Expect(getScopeFromImageAuthURL("ghcr.io/nicholas-fedor/watchtower")).To(Equal("nicholas-fedor/watchtower"))
|
||||
// })
|
||||
})
|
||||
It("should not crash when an empty field is received", func() {
|
||||
input := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull",`
|
||||
imageRef, err := ref.ParseNormalizedNamed("containrrr/watchtower")
|
||||
imageRef, err := ref.ParseNormalizedNamed("nicholas-fedor/watchtower")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
res, err := auth.GetAuthURL(input, imageRef)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -122,7 +118,7 @@ var _ = Describe("the auth module", func() {
|
|||
})
|
||||
It("should not crash when a field without a value is received", func() {
|
||||
input := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull",valuelesskey`
|
||||
imageRef, err := ref.ParseNormalizedNamed("containrrr/watchtower")
|
||||
imageRef, err := ref.ParseNormalizedNamed("nicholas-fedor/watchtower")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
res, err := auth.GetAuthURL(input, imageRef)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -133,17 +129,17 @@ var _ = Describe("the auth module", func() {
|
|||
Describe("GetChallengeURL", func() {
|
||||
It("should create a valid challenge url object based on the image ref supplied", func() {
|
||||
expected := url.URL{Host: "ghcr.io", Scheme: "https", Path: "/v2/"}
|
||||
imageRef, _ := ref.ParseNormalizedNamed("ghcr.io/containrrr/watchtower:latest")
|
||||
imageRef, _ := ref.ParseNormalizedNamed("ghcr.io/nicholas-fedor/watchtower:latest")
|
||||
Expect(auth.GetChallengeURL(imageRef)).To(Equal(expected))
|
||||
})
|
||||
It("should assume Docker Hub for image refs with no explicit registry", func() {
|
||||
expected := url.URL{Host: "index.docker.io", Scheme: "https", Path: "/v2/"}
|
||||
imageRef, _ := ref.ParseNormalizedNamed("containrrr/watchtower:latest")
|
||||
imageRef, _ := ref.ParseNormalizedNamed("nickfedor/watchtower:latest")
|
||||
Expect(auth.GetChallengeURL(imageRef)).To(Equal(expected))
|
||||
})
|
||||
It("should use index.docker.io if the image ref specifies docker.io", func() {
|
||||
expected := url.URL{Host: "index.docker.io", Scheme: "https", Path: "/v2/"}
|
||||
imageRef, _ := ref.ParseNormalizedNamed("docker.io/containrrr/watchtower:latest")
|
||||
imageRef, _ := ref.ParseNormalizedNamed("docker.io/nickfedor/watchtower:latest")
|
||||
Expect(auth.GetChallengeURL(imageRef)).To(Equal(expected))
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/internal/meta"
|
||||
"github.com/containrrr/watchtower/pkg/registry/auth"
|
||||
"github.com/containrrr/watchtower/pkg/registry/manifest"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/internal/meta"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/auth"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/manifest"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package digest_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/registry/digest"
|
||||
wtTypes "github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/internal/actions/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/digest"
|
||||
wtTypes "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/ghttp"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/distribution/reference"
|
||||
)
|
||||
|
||||
// domains for Docker Hub, the default registry
|
||||
|
|
|
|||
|
|
@ -20,18 +20,18 @@ var _ = Describe("the helpers", func() {
|
|||
})
|
||||
It("should return index.docker.io for image refs with no explicit registry", func() {
|
||||
Expect(GetRegistryAddress("watchtower")).To(Equal("index.docker.io"))
|
||||
Expect(GetRegistryAddress("containrrr/watchtower")).To(Equal("index.docker.io"))
|
||||
Expect(GetRegistryAddress("nickfedor/watchtower")).To(Equal("index.docker.io"))
|
||||
})
|
||||
It("should return index.docker.io for image refs with docker.io domain", func() {
|
||||
Expect(GetRegistryAddress("docker.io/watchtower")).To(Equal("index.docker.io"))
|
||||
Expect(GetRegistryAddress("docker.io/containrrr/watchtower")).To(Equal("index.docker.io"))
|
||||
Expect(GetRegistryAddress("docker.io/nickfedor/watchtower")).To(Equal("index.docker.io"))
|
||||
})
|
||||
It("should return the host if passed an image name containing a local host", func() {
|
||||
Expect(GetRegistryAddress("henk:80/watchtower")).To(Equal("henk:80"))
|
||||
Expect(GetRegistryAddress("localhost/watchtower")).To(Equal("localhost"))
|
||||
})
|
||||
It("should return the server address if passed a fully qualified image name", func() {
|
||||
Expect(GetRegistryAddress("github.com/containrrr/config")).To(Equal("github.com"))
|
||||
Expect(GetRegistryAddress("github.com/nicholas-fedor/config")).To(Equal("github.com"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import (
|
|||
"fmt"
|
||||
url2 "net/url"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/registry/helpers"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
ref "github.com/docker/distribution/reference"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/helpers"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
ref "github.com/distribution/reference"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/registry/manifest"
|
||||
apiTypes "github.com/docker/docker/api/types"
|
||||
"github.com/nicholas-fedor/watchtower/internal/actions/mocks"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/manifest"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
@ -19,24 +19,24 @@ func TestManifest(t *testing.T) {
|
|||
var _ = Describe("the manifest module", func() {
|
||||
Describe("BuildManifestURL", func() {
|
||||
It("should return a valid url given a fully qualified image", func() {
|
||||
imageRef := "ghcr.io/containrrr/watchtower:mytag"
|
||||
expected := "https://ghcr.io/v2/containrrr/watchtower/manifests/mytag"
|
||||
imageRef := "ghcr.io/nicholas-fedor/watchtower:mytag"
|
||||
expected := "https://ghcr.io/v2/nicholas-fedor/watchtower/manifests/mytag"
|
||||
|
||||
URL, err := buildMockContainerManifestURL(imageRef)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(URL).To(Equal(expected))
|
||||
})
|
||||
It("should assume Docker Hub for image refs with no explicit registry", func() {
|
||||
imageRef := "containrrr/watchtower:latest"
|
||||
expected := "https://index.docker.io/v2/containrrr/watchtower/manifests/latest"
|
||||
imageRef := "nickfedor/watchtower:latest"
|
||||
expected := "https://index.docker.io/v2/nickfedor/watchtower/manifests/latest"
|
||||
|
||||
URL, err := buildMockContainerManifestURL(imageRef)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(URL).To(Equal(expected))
|
||||
})
|
||||
It("should assume latest for image refs with no explicit tag", func() {
|
||||
imageRef := "containrrr/watchtower"
|
||||
expected := "https://index.docker.io/v2/containrrr/watchtower/manifests/latest"
|
||||
imageRef := "nickfedor/watchtower"
|
||||
expected := "https://index.docker.io/v2/nickfedor/watchtower/manifests/latest"
|
||||
|
||||
URL, err := buildMockContainerManifestURL(imageRef)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
|
|||
|
|
@ -1,29 +1,31 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/registry/helpers"
|
||||
watchtowerTypes "github.com/containrrr/watchtower/pkg/types"
|
||||
ref "github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"context"
|
||||
|
||||
ref "github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/helpers"
|
||||
watchtowerTypes "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// GetPullOptions creates a struct with all options needed for pulling images from a registry
|
||||
func GetPullOptions(imageName string) (types.ImagePullOptions, error) {
|
||||
func GetPullOptions(imageName string) (image.PullOptions, error) {
|
||||
auth, err := EncodedAuth(imageName)
|
||||
log.Debugf("Got image name: %s", imageName)
|
||||
if err != nil {
|
||||
return types.ImagePullOptions{}, err
|
||||
return image.PullOptions{}, err
|
||||
}
|
||||
|
||||
if auth == "" {
|
||||
return types.ImagePullOptions{}, nil
|
||||
return image.PullOptions{}, nil
|
||||
}
|
||||
|
||||
// CREDENTIAL: Uncomment to log docker config auth
|
||||
// log.Tracef("Got auth value: %s", auth)
|
||||
|
||||
return types.ImagePullOptions{
|
||||
return image.PullOptions{
|
||||
RegistryAuth: auth,
|
||||
PrivilegeFunc: DefaultAuthHandler,
|
||||
}, nil
|
||||
|
|
@ -32,7 +34,7 @@ func GetPullOptions(imageName string) (types.ImagePullOptions, error) {
|
|||
// DefaultAuthHandler will be invoked if an AuthConfig is rejected
|
||||
// It could be used to return a new value for the "X-Registry-Auth" authentication header,
|
||||
// but there's no point trying again with the same value as used in AuthConfig
|
||||
func DefaultAuthHandler() (string, error) {
|
||||
func DefaultAuthHandler(context.Context) (string, error) {
|
||||
log.Debug("Authentication request was rejected. Trying again without authentication")
|
||||
return "", nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package registry_test
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
unit "github.com/containrrr/watchtower/pkg/registry"
|
||||
"github.com/nicholas-fedor/watchtower/internal/actions/mocks"
|
||||
unit "github.com/nicholas-fedor/watchtower/pkg/registry"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ var _ = Describe("Registry", func() {
|
|||
Describe("WarnOnAPIConsumption", func() {
|
||||
When("Given a container with an image from ghcr.io", func() {
|
||||
It("should want to warn", func() {
|
||||
Expect(testContainerWithImage("ghcr.io/containrrr/watchtower")).To(BeTrue())
|
||||
Expect(testContainerWithImage("ghcr.io/nicholas-fedor/watchtower")).To(BeTrue())
|
||||
})
|
||||
})
|
||||
When("Given a container with an image implicitly from dockerhub", func() {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/registry/helpers"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/registry/helpers"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/config/credentials"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package session
|
||||
|
||||
import wt "github.com/containrrr/watchtower/pkg/types"
|
||||
import wt "github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
|
||||
// State indicates what the current state is of the container
|
||||
type State int
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
// Progress contains the current session container status
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package session
|
|||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
type report struct {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
"github.com/nicholas-fedor/watchtower/pkg/types"
|
||||
)
|
||||
|
||||
// ByCreated allows a list of Container structs to be sorted by the container's
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue