You've already forked watchtower
							
							
				mirror of
				https://github.com/containrrr/watchtower.git
				synced 2025-10-31 00:17:44 +02:00 
			
		
		
		
	refactor: extract types and pkgs to new files
This commit is contained in:
		| @@ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/containrrr/watchtower/container/mocks" | ||||
| 	"github.com/docker/docker/api/types" | ||||
|  | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| 	cli "github.com/docker/docker/client" | ||||
|  | ||||
| 	. "github.com/onsi/ginkgo" | ||||
| @@ -149,7 +150,7 @@ type TestData struct { | ||||
| 	Containers            []container.Container | ||||
| } | ||||
|  | ||||
| func (client mockClient) ListContainers(f container.Filter) ([]container.Container, error) { | ||||
| func (client mockClient) ListContainers(f t.Filter) ([]container.Container, error) { | ||||
| 	return client.TestData.Containers, nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/containrrr/watchtower/container" | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| @@ -14,7 +15,7 @@ var ( | ||||
|  | ||||
| // UpdateParams contains all different options available to alter the behavior of the Update func | ||||
| type UpdateParams struct { | ||||
| 	Filter      container.Filter | ||||
| 	Filter      t.Filter | ||||
| 	Cleanup     bool | ||||
| 	NoRestart   bool | ||||
| 	Timeout     time.Duration | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import ( | ||||
| 	"github.com/containrrr/watchtower/container" | ||||
| 	"github.com/containrrr/watchtower/internal/flags" | ||||
| 	"github.com/containrrr/watchtower/notifications" | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| 	"github.com/robfig/cron" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
|  | ||||
| @@ -123,7 +124,7 @@ func Run(c *cobra.Command, names []string) { | ||||
| 	os.Exit(1) | ||||
| } | ||||
|  | ||||
| func runUpgradesOnSchedule(filter container.Filter) error { | ||||
| func runUpgradesOnSchedule(filter t.Filter) error { | ||||
| 	tryLockSem := make(chan bool, 1) | ||||
| 	tryLockSem <- true | ||||
|  | ||||
| @@ -164,7 +165,7 @@ func runUpgradesOnSchedule(filter container.Filter) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func runUpdatesWithNotifications(filter container.Filter) { | ||||
| func runUpdatesWithNotifications(filter t.Filter) { | ||||
| 	notifier.StartNotification() | ||||
| 	updateParams := actions.UpdateParams{ | ||||
| 		Filter:      filter, | ||||
|   | ||||
| @@ -5,10 +5,10 @@ import ( | ||||
| 	"io/ioutil" | ||||
| 	"time" | ||||
|  | ||||
| 	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" | ||||
| 	"github.com/docker/docker/api/types/network" | ||||
| 	dockerclient "github.com/docker/docker/client" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| @@ -22,7 +22,7 @@ const ( | ||||
| // A Client is the interface through which watchtower interacts with the | ||||
| // Docker API. | ||||
| type Client interface { | ||||
| 	ListContainers(Filter) ([]Container, error) | ||||
| 	ListContainers(t.Filter) ([]Container, error) | ||||
| 	StopContainer(Container, time.Duration) error | ||||
| 	StartContainer(Container) error | ||||
| 	RenameContainer(Container, string) error | ||||
| @@ -58,7 +58,7 @@ type dockerClient struct { | ||||
| 	includeStopped bool | ||||
| } | ||||
|  | ||||
| func (client dockerClient) ListContainers(fn Filter) ([]Container, error) { | ||||
| func (client dockerClient) ListContainers(fn t.Filter) ([]Container, error) { | ||||
| 	cs := []Container{} | ||||
| 	bg := context.Background() | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package container | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/containrrr/watchtower/internal/util" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| @@ -146,19 +147,19 @@ func (c Container) runtimeConfig() *dockercontainer.Config { | ||||
| 		config.User = "" | ||||
| 	} | ||||
|  | ||||
| 	if sliceEqual(config.Cmd, imageConfig.Cmd) { | ||||
| 	if util.SliceEqual(config.Cmd, imageConfig.Cmd) { | ||||
| 		config.Cmd = nil | ||||
| 	} | ||||
|  | ||||
| 	if sliceEqual(config.Entrypoint, imageConfig.Entrypoint) { | ||||
| 	if util.SliceEqual(config.Entrypoint, imageConfig.Entrypoint) { | ||||
| 		config.Entrypoint = nil | ||||
| 	} | ||||
|  | ||||
| 	config.Env = sliceSubtract(config.Env, imageConfig.Env) | ||||
| 	config.Env = util.SliceSubtract(config.Env, imageConfig.Env) | ||||
|  | ||||
| 	config.Labels = stringMapSubtract(config.Labels, imageConfig.Labels) | ||||
| 	config.Labels = util.StringMapSubtract(config.Labels, imageConfig.Labels) | ||||
|  | ||||
| 	config.Volumes = structMapSubtract(config.Volumes, imageConfig.Volumes) | ||||
| 	config.Volumes = util.StructMapSubtract(config.Volumes, imageConfig.Volumes) | ||||
|  | ||||
| 	// subtract ports exposed in image from container | ||||
| 	for k := range config.ExposedPorts { | ||||
|   | ||||
| @@ -1,30 +1,20 @@ | ||||
| package container | ||||
|  | ||||
| // A Filter is a prototype for a function that can be used to filter the | ||||
| // results from a call to the ListContainers() method on the Client. | ||||
| type Filter func(FilterableContainer) bool | ||||
|  | ||||
| // A FilterableContainer is the interface which is used to filter | ||||
| // containers. | ||||
| type FilterableContainer interface { | ||||
| 	Name() string | ||||
| 	IsWatchtower() bool | ||||
| 	Enabled() (bool, bool) | ||||
| } | ||||
| import t "github.com/containrrr/watchtower/pkg/types" | ||||
|  | ||||
| // WatchtowerContainersFilter filters only watchtower containers | ||||
| func WatchtowerContainersFilter(c FilterableContainer) bool { return c.IsWatchtower() } | ||||
| func WatchtowerContainersFilter(c t.FilterableContainer) bool { return c.IsWatchtower() } | ||||
|  | ||||
| // Filter no containers and returns all | ||||
| func noFilter(FilterableContainer) bool { return true } | ||||
| func noFilter(t.FilterableContainer) bool { return true } | ||||
|  | ||||
| // Filters containers which don't have a specified name | ||||
| func filterByNames(names []string, baseFilter Filter) Filter { | ||||
| func filterByNames(names []string, baseFilter t.Filter) t.Filter { | ||||
| 	if len(names) == 0 { | ||||
| 		return baseFilter | ||||
| 	} | ||||
|  | ||||
| 	return func(c FilterableContainer) bool { | ||||
| 	return func(c t.FilterableContainer) bool { | ||||
| 		for _, name := range names { | ||||
| 			if (name == c.Name()) || (name == c.Name()[1:]) { | ||||
| 				return baseFilter(c) | ||||
| @@ -35,8 +25,8 @@ func filterByNames(names []string, baseFilter Filter) Filter { | ||||
| } | ||||
|  | ||||
| // Filters out containers that don't have the 'enableLabel' | ||||
| func filterByEnableLabel(baseFilter Filter) Filter { | ||||
| 	return func(c FilterableContainer) bool { | ||||
| func filterByEnableLabel(baseFilter t.Filter) t.Filter { | ||||
| 	return func(c t.FilterableContainer) bool { | ||||
| 		// If label filtering is enabled, containers should only be considered | ||||
| 		// if the label is specifically set. | ||||
| 		_, ok := c.Enabled() | ||||
| @@ -49,8 +39,8 @@ func filterByEnableLabel(baseFilter Filter) Filter { | ||||
| } | ||||
|  | ||||
| // Filters out containers that have a 'enableLabel' and is set to disable. | ||||
| func filterByDisabledLabel(baseFilter Filter) Filter { | ||||
| 	return func(c FilterableContainer) bool { | ||||
| func filterByDisabledLabel(baseFilter t.Filter) t.Filter { | ||||
| 	return func(c t.FilterableContainer) bool { | ||||
| 		enabledLabel, ok := c.Enabled() | ||||
| 		if ok && !enabledLabel { | ||||
| 			// If the label has been set and it demands a disable | ||||
| @@ -62,7 +52,7 @@ func filterByDisabledLabel(baseFilter Filter) Filter { | ||||
| } | ||||
|  | ||||
| // BuildFilter creates the needed filter of containers | ||||
| func BuildFilter(names []string, enableLabel bool) Filter { | ||||
| func BuildFilter(names []string, enableLabel bool) t.Filter { | ||||
| 	filter := noFilter | ||||
| 	filter = filterByNames(names, filter) | ||||
| 	if enableLabel { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| package container | ||||
| package util | ||||
| 
 | ||||
| func sliceEqual(s1, s2 []string) bool { | ||||
| func SliceEqual(s1, s2 []string) bool { | ||||
| 	if len(s1) != len(s2) { | ||||
| 		return false | ||||
| 	} | ||||
| @@ -14,7 +14,7 @@ func sliceEqual(s1, s2 []string) bool { | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func sliceSubtract(a1, a2 []string) []string { | ||||
| func SliceSubtract(a1, a2 []string) []string { | ||||
| 	a := []string{} | ||||
| 
 | ||||
| 	for _, e1 := range a1 { | ||||
| @@ -35,7 +35,7 @@ func sliceSubtract(a1, a2 []string) []string { | ||||
| 	return a | ||||
| } | ||||
| 
 | ||||
| func stringMapSubtract(m1, m2 map[string]string) map[string]string { | ||||
| func StringMapSubtract(m1, m2 map[string]string) map[string]string { | ||||
| 	m := map[string]string{} | ||||
| 
 | ||||
| 	for k1, v1 := range m1 { | ||||
| @@ -51,7 +51,7 @@ func stringMapSubtract(m1, m2 map[string]string) map[string]string { | ||||
| 	return m | ||||
| } | ||||
| 
 | ||||
| func structMapSubtract(m1, m2 map[string]struct{}) map[string]struct{} { | ||||
| func StructMapSubtract(m1, m2 map[string]struct{}) map[string]struct{} { | ||||
| 	m := map[string]struct{}{} | ||||
| 
 | ||||
| 	for k1, v1 := range m1 { | ||||
| @@ -1,8 +1,8 @@ | ||||
| package container | ||||
| package util | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| @@ -11,7 +11,7 @@ func TestSliceEqual_True(t *testing.T) { | ||||
| 	s1 := []string{"a", "b", "c"} | ||||
| 	s2 := []string{"a", "b", "c"} | ||||
| 
 | ||||
| 	result := sliceEqual(s1, s2) | ||||
| 	result := SliceEqual(s1, s2) | ||||
| 
 | ||||
| 	assert.True(t, result) | ||||
| } | ||||
| @@ -20,7 +20,7 @@ func TestSliceEqual_DifferentLengths(t *testing.T) { | ||||
| 	s1 := []string{"a", "b", "c"} | ||||
| 	s2 := []string{"a", "b", "c", "d"} | ||||
| 
 | ||||
| 	result := sliceEqual(s1, s2) | ||||
| 	result := SliceEqual(s1, s2) | ||||
| 
 | ||||
| 	assert.False(t, result) | ||||
| } | ||||
| @@ -29,7 +29,7 @@ func TestSliceEqual_DifferentContents(t *testing.T) { | ||||
| 	s1 := []string{"a", "b", "c"} | ||||
| 	s2 := []string{"a", "b", "d"} | ||||
| 
 | ||||
| 	result := sliceEqual(s1, s2) | ||||
| 	result := SliceEqual(s1, s2) | ||||
| 
 | ||||
| 	assert.False(t, result) | ||||
| } | ||||
| @@ -38,7 +38,7 @@ func TestSliceSubtract(t *testing.T) { | ||||
| 	a1 := []string{"a", "b", "c"} | ||||
| 	a2 := []string{"a", "c"} | ||||
| 
 | ||||
| 	result := sliceSubtract(a1, a2) | ||||
| 	result := SliceSubtract(a1, a2) | ||||
| 	assert.Equal(t, []string{"b"}, result) | ||||
| 	assert.Equal(t, []string{"a", "b", "c"}, a1) | ||||
| 	assert.Equal(t, []string{"a", "c"}, a2) | ||||
| @@ -48,7 +48,7 @@ func TestStringMapSubtract(t *testing.T) { | ||||
| 	m1 := map[string]string{"a": "a", "b": "b", "c": "sea"} | ||||
| 	m2 := map[string]string{"a": "a", "c": "c"} | ||||
| 
 | ||||
| 	result := stringMapSubtract(m1, m2) | ||||
| 	result := StringMapSubtract(m1, m2) | ||||
| 	assert.Equal(t, map[string]string{"b": "b", "c": "sea"}, result) | ||||
| 	assert.Equal(t, map[string]string{"a": "a", "b": "b", "c": "sea"}, m1) | ||||
| 	assert.Equal(t, map[string]string{"a": "a", "c": "c"}, m2) | ||||
| @@ -59,7 +59,7 @@ func TestStructMapSubtract(t *testing.T) { | ||||
| 	m1 := map[string]struct{}{"a": x, "b": x, "c": x} | ||||
| 	m2 := map[string]struct{}{"a": x, "c": x} | ||||
| 
 | ||||
| 	result := structMapSubtract(m1, m2) | ||||
| 	result := StructMapSubtract(m1, m2) | ||||
| 	assert.Equal(t, map[string]struct{}{"b": x}, result) | ||||
| 	assert.Equal(t, map[string]struct{}{"a": x, "b": x, "c": x}, m1) | ||||
| 	assert.Equal(t, map[string]struct{}{"a": x, "c": x}, m2) | ||||
| @@ -9,7 +9,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"strconv" | ||||
|  | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| @@ -17,7 +17,7 @@ const ( | ||||
| 	emailType = "email" | ||||
| ) | ||||
|  | ||||
| // Implements typeNotifier, logrus.Hook | ||||
| // Implements Notifier, logrus.Hook | ||||
| // The default logrus email integration would have several issues: | ||||
| // - It would send one email per log output | ||||
| // - It would only send errors | ||||
| @@ -31,7 +31,7 @@ type emailTypeNotifier struct { | ||||
| 	logLevels              []log.Level | ||||
| } | ||||
|  | ||||
| func newEmailNotifier(c *cobra.Command, acceptedLogLevels []log.Level) typeNotifier { | ||||
| func newEmailNotifier(c *cobra.Command, acceptedLogLevels []log.Level) t.Notifier { | ||||
| 	flags := c.PersistentFlags() | ||||
|  | ||||
| 	from, _ := flags.GetString("notification-email-from") | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"net/http" | ||||
|  | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"io/ioutil" | ||||
| ) | ||||
| @@ -21,7 +22,7 @@ type msTeamsTypeNotifier struct { | ||||
| 	data       bool | ||||
| } | ||||
|  | ||||
| func newMsTeamsNotifier(cmd *cobra.Command, acceptedLogLevels []log.Level) typeNotifier { | ||||
| func newMsTeamsNotifier(cmd *cobra.Command, acceptedLogLevels []log.Level) t.Notifier { | ||||
|  | ||||
| 	flags := cmd.PersistentFlags() | ||||
|  | ||||
|   | ||||
| @@ -1,19 +1,17 @@ | ||||
| package notifications | ||||
|  | ||||
| import ( | ||||
| 	ty "github.com/containrrr/watchtower/pkg/types" | ||||
| 	"github.com/johntdyer/slackrus" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| type typeNotifier interface { | ||||
| 	StartNotification() | ||||
| 	SendNotification() | ||||
| } | ||||
|  | ||||
|  | ||||
| // Notifier can send log output as notification to admins, with optional batching. | ||||
| type Notifier struct { | ||||
| 	types []typeNotifier | ||||
| 	types []ty.Notifier | ||||
| } | ||||
|  | ||||
| // NewNotifier creates and returns a new Notifier, using global configuration. | ||||
| @@ -34,7 +32,7 @@ func NewNotifier(c *cobra.Command) *Notifier { | ||||
| 	types, _ := f.GetStringSlice("notifications") | ||||
|  | ||||
| 	for _, t := range types { | ||||
| 		var tn typeNotifier | ||||
| 		var tn ty.Notifier | ||||
| 		switch t { | ||||
| 		case emailType: | ||||
| 			tn = newEmailNotifier(c, acceptedLogLevels) | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"github.com/johntdyer/slackrus" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	t "github.com/containrrr/watchtower/pkg/types" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| @@ -14,7 +15,7 @@ type slackTypeNotifier struct { | ||||
| 	slackrus.SlackrusHook | ||||
| } | ||||
|  | ||||
| func newSlackNotifier(c *cobra.Command, acceptedLogLevels []log.Level) typeNotifier { | ||||
| func newSlackNotifier(c *cobra.Command, acceptedLogLevels []log.Level) t.Notifier { | ||||
| 	flags := c.PersistentFlags() | ||||
|  | ||||
| 	hookURL,  _ := flags.GetString("notification-slack-hook-url") | ||||
|   | ||||
							
								
								
									
										5
									
								
								pkg/types/filter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								pkg/types/filter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| package types | ||||
|  | ||||
| // A Filter is a prototype for a function that can be used to filter the | ||||
| // results from a call to the ListContainers() method on the Client. | ||||
| type Filter func(FilterableContainer) bool | ||||
							
								
								
									
										9
									
								
								pkg/types/filterable_container.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								pkg/types/filterable_container.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package types | ||||
|  | ||||
| // A FilterableContainer is the interface which is used to filter | ||||
| // containers. | ||||
| type FilterableContainer interface { | ||||
| 	Name() string | ||||
| 	IsWatchtower() bool | ||||
| 	Enabled() (bool, bool) | ||||
| } | ||||
							
								
								
									
										6
									
								
								pkg/types/notifier.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								pkg/types/notifier.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| package types | ||||
|  | ||||
| type Notifier interface { | ||||
| 	StartNotification() | ||||
| 	SendNotification() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user