1
0
mirror of https://github.com/containrrr/watchtower.git synced 2024-12-12 09:04:17 +02:00
watchtower/pkg/container/container_test.go
yrien30 2842b97df3
Allow watchtower to update rebooting containers (#651)
Co-authored-by: nils måsén <nils@piksel.se>
Co-authored-by: Simon Aronsson <simme@arcticbit.se>
2020-11-19 19:03:17 +01:00

298 lines
9.7 KiB
Go

package container
import (
"testing"
"github.com/containrrr/watchtower/pkg/container/mocks"
"github.com/containrrr/watchtower/pkg/filters"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
cli "github.com/docker/docker/client"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestContainer(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Container Suite")
}
var _ = Describe("the container", func() {
Describe("the client", func() {
var docker *cli.Client
var client Client
BeforeSuite(func() {
server := mocks.NewMockAPIServer()
docker, _ = cli.NewClientWithOpts(
cli.WithHost(server.URL),
cli.WithHTTPClient(server.Client()))
client = dockerClient{
api: docker,
pullImages: false,
}
})
It("should return a client for the api", func() {
Expect(client).NotTo(BeNil())
})
When("listing containers without any filter", func() {
It("should return all available containers", func() {
containers, err := client.ListContainers(filters.NoFilter)
Expect(err).NotTo(HaveOccurred())
Expect(len(containers) == 2).To(BeTrue())
})
})
When("listing containers with a filter matching nothing", func() {
It("should return an empty array", func() {
filter := filters.FilterByNames([]string{"lollercoaster"}, filters.NoFilter)
containers, err := client.ListContainers(filter)
Expect(err).NotTo(HaveOccurred())
Expect(len(containers) == 0).To(BeTrue())
})
})
When("listing containers with a watchtower filter", func() {
It("should return only the watchtower container", func() {
containers, err := client.ListContainers(filters.WatchtowerContainersFilter)
Expect(err).NotTo(HaveOccurred())
Expect(len(containers) == 1).To(BeTrue())
Expect(containers[0].ImageName()).To(Equal("containrrr/watchtower:latest"))
})
})
When(`listing containers with the "include stopped" option`, func() {
It("should return both stopped and running containers", func() {
client = dockerClient{
api: docker,
pullImages: false,
includeStopped: true,
}
containers, err := client.ListContainers(filters.NoFilter)
Expect(err).NotTo(HaveOccurred())
Expect(len(containers) > 0).To(BeTrue())
})
})
When(`listing containers with the "include restart" option`, func() {
It("should return both stopped, restarting and running containers", func() {
client = dockerClient{
api: docker,
pullImages: false,
includeRestarting: true,
}
containers, err := client.ListContainers(filters.NoFilter)
Expect(err).NotTo(HaveOccurred())
RestartingContainerFound := false
for _, ContainerRunning := range containers {
if ContainerRunning.containerInfo.State.Restarting {
RestartingContainerFound = true
}
}
Expect(RestartingContainerFound).To(BeTrue())
Expect(RestartingContainerFound).NotTo(BeFalse())
})
})
When(`listing containers without restarting ones`, func() {
It("should not return restarting containers", func() {
client = dockerClient{
api: docker,
pullImages: false,
includeRestarting: false,
}
containers, err := client.ListContainers(filters.NoFilter)
Expect(err).NotTo(HaveOccurred())
RestartingContainerFound := false
for _, ContainerRunning := range containers {
if ContainerRunning.containerInfo.State.Restarting {
RestartingContainerFound = true
}
}
Expect(RestartingContainerFound).To(BeFalse())
Expect(RestartingContainerFound).NotTo(BeTrue())
})
})
})
When("asked for metadata", func() {
var c *Container
BeforeEach(func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.watchtower.enable": "true",
"com.centurylinklabs.watchtower": "true",
})
})
It("should return its name on calls to .Name()", func() {
name := c.Name()
Expect(name).To(Equal("test-containrrr"))
Expect(name).NotTo(Equal("wrong-name"))
})
It("should return its ID on calls to .ID()", func() {
id := c.ID()
Expect(id).To(Equal("container_id"))
Expect(id).NotTo(Equal("wrong-id"))
})
It("should return true, true if enabled on calls to .Enabled()", func() {
enabled, exists := c.Enabled()
Expect(enabled).To(BeTrue())
Expect(enabled).NotTo(BeFalse())
Expect(exists).To(BeTrue())
Expect(exists).NotTo(BeFalse())
})
It("should return false, true if present but not true on calls to .Enabled()", func() {
c = mockContainerWithLabels(map[string]string{"com.centurylinklabs.watchtower.enable": "false"})
enabled, exists := c.Enabled()
Expect(enabled).To(BeFalse())
Expect(enabled).NotTo(BeTrue())
Expect(exists).To(BeTrue())
Expect(exists).NotTo(BeFalse())
})
It("should return false, false if not present on calls to .Enabled()", func() {
c = mockContainerWithLabels(map[string]string{"lol": "false"})
enabled, exists := c.Enabled()
Expect(enabled).To(BeFalse())
Expect(enabled).NotTo(BeTrue())
Expect(exists).To(BeFalse())
Expect(exists).NotTo(BeTrue())
})
It("should return false, false if present but not parsable .Enabled()", func() {
c = mockContainerWithLabels(map[string]string{"com.centurylinklabs.watchtower.enable": "falsy"})
enabled, exists := c.Enabled()
Expect(enabled).To(BeFalse())
Expect(enabled).NotTo(BeTrue())
Expect(exists).To(BeFalse())
Expect(exists).NotTo(BeTrue())
})
When("checking if its a watchtower instance", func() {
It("should return true if the label is set to true", func() {
isWatchtower := c.IsWatchtower()
Expect(isWatchtower).To(BeTrue())
})
It("should return false if the label is present but set to false", func() {
c = mockContainerWithLabels(map[string]string{"com.centurylinklabs.watchtower": "false"})
isWatchtower := c.IsWatchtower()
Expect(isWatchtower).To(BeFalse())
})
It("should return false if the label is not present", func() {
c = mockContainerWithLabels(map[string]string{"funny.label": "false"})
isWatchtower := c.IsWatchtower()
Expect(isWatchtower).To(BeFalse())
})
It("should return false if there are no labels", func() {
c = mockContainerWithLabels(map[string]string{})
isWatchtower := c.IsWatchtower()
Expect(isWatchtower).To(BeFalse())
})
})
When("fetching the custom stop signal", func() {
It("should return the signal if its set", func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.watchtower.stop-signal": "SIGKILL",
})
stopSignal := c.StopSignal()
Expect(stopSignal).To(Equal("SIGKILL"))
})
It("should return an empty string if its not set", func() {
c = mockContainerWithLabels(map[string]string{})
stopSignal := c.StopSignal()
Expect(stopSignal).To(Equal(""))
})
})
When("fetching the image name", func() {
When("the zodiac label is present", func() {
It("should fetch the image name from it", func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.zodiac.original-image": "the-original-image",
})
imageName := c.ImageName()
Expect(imageName).To(Equal(imageName))
})
})
It("should return the image name", func() {
name := "image-name:3"
c = mockContainerWithImageName(name)
imageName := c.ImageName()
Expect(imageName).To(Equal(name))
})
It("should assume latest if no tag is supplied", func() {
name := "image-name"
c = mockContainerWithImageName(name)
imageName := c.ImageName()
Expect(imageName).To(Equal(name + ":latest"))
})
})
When("fetching container links", func() {
When("the depends on label is present", func() {
It("should fetch depending containers from it", func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.watchtower.depends-on": "postgres",
})
links := c.Links()
Expect(links).To(SatisfyAll(ContainElement("postgres"), HaveLen(1)))
})
It("should fetch depending containers if there are many", func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.watchtower.depends-on": "postgres,redis",
})
links := c.Links()
Expect(links).To(SatisfyAll(ContainElement("postgres"), ContainElement("redis"), HaveLen(2)))
})
It("should fetch depending containers if label is blank", func() {
c = mockContainerWithLabels(map[string]string{
"com.centurylinklabs.watchtower.depends-on": "",
})
links := c.Links()
Expect(links).To(HaveLen(0))
})
})
When("the depends on label is not present", func() {
It("should fetch depending containers from host config links", func() {
c = mockContainerWithLinks([]string{
"redis:test-containrrr",
"postgres:test-containrrr",
})
links := c.Links()
Expect(links).To(SatisfyAll(ContainElement("redis"), ContainElement("postgres"), HaveLen(2)))
})
})
})
})
})
func mockContainerWithImageName(name string) *Container {
container := mockContainerWithLabels(nil)
container.containerInfo.Config.Image = name
return container
}
func mockContainerWithLinks(links []string) *Container {
content := types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
ID: "container_id",
Image: "image",
Name: "test-containrrr",
HostConfig: &container.HostConfig{
Links: links,
},
},
Config: &container.Config{
Labels: map[string]string{},
},
}
return NewContainer(&content, nil)
}
func mockContainerWithLabels(labels map[string]string) *Container {
content := types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
ID: "container_id",
Image: "image",
Name: "test-containrrr",
},
Config: &container.Config{
Labels: labels,
},
}
return NewContainer(&content, nil)
}