You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
watchtower/container/client_test.go

437 lines
12 KiB
Go

package container
import (
"errors"
"testing"
"time"
"github.com/samalba/dockerclient"
"github.com/samalba/dockerclient/mockclient"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func allContainers(Container) bool { return true }
func noContainers(Container) bool { return false }
func TestListContainers_Success(t *testing.T) {
ci := &dockerclient.ContainerInfo{Image: "abc123", Config: &dockerclient.ContainerConfig{Image: "img"}}
ii := &dockerclient.ImageInfo{}
api := mockclient.NewMockClient()
api.On("ListContainers", false, false, "").Return([]dockerclient.Container{{Id: "foo", Names: []string{"bar"}}}, nil)
api.On("InspectContainer", "foo").Return(ci, nil)
api.On("InspectImage", "abc123").Return(ii, nil)
client := dockerClient{api: api}
cs, err := client.ListContainers(allContainers)
assert.NoError(t, err)
assert.Len(t, cs, 1)
assert.Equal(t, ci, cs[0].containerInfo)
assert.Equal(t, ii, cs[0].imageInfo)
api.AssertExpectations(t)
}
func TestListContainers_Filter(t *testing.T) {
ci := &dockerclient.ContainerInfo{Image: "abc123", Config: &dockerclient.ContainerConfig{Image: "img"}}
ii := &dockerclient.ImageInfo{}
api := mockclient.NewMockClient()
api.On("ListContainers", false, false, "").Return([]dockerclient.Container{{Id: "foo", Names: []string{"bar"}}}, nil)
api.On("InspectContainer", "foo").Return(ci, nil)
api.On("InspectImage", "abc123").Return(ii, nil)
client := dockerClient{api: api}
cs, err := client.ListContainers(noContainers)
assert.NoError(t, err)
assert.Len(t, cs, 0)
api.AssertExpectations(t)
}
func TestListContainers_ListError(t *testing.T) {
api := mockclient.NewMockClient()
api.On("ListContainers", false, false, "").Return([]dockerclient.Container{}, errors.New("oops"))
client := dockerClient{api: api}
_, err := client.ListContainers(allContainers)
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}
func TestListContainers_InspectContainerError(t *testing.T) {
api := mockclient.NewMockClient()
api.On("ListContainers", false, false, "").Return([]dockerclient.Container{{Id: "foo", Names: []string{"bar"}}}, nil)
api.On("InspectContainer", "foo").Return(&dockerclient.ContainerInfo{}, errors.New("uh-oh"))
client := dockerClient{api: api}
_, err := client.ListContainers(allContainers)
assert.Error(t, err)
assert.EqualError(t, err, "uh-oh")
api.AssertExpectations(t)
}
func TestListContainers_InspectImageError(t *testing.T) {
ci := &dockerclient.ContainerInfo{Image: "abc123", Config: &dockerclient.ContainerConfig{Image: "img"}}
ii := &dockerclient.ImageInfo{}
api := mockclient.NewMockClient()
api.On("ListContainers", false, false, "").Return([]dockerclient.Container{{Id: "foo", Names: []string{"bar"}}}, nil)
api.On("InspectContainer", "foo").Return(ci, nil)
api.On("InspectImage", "abc123").Return(ii, errors.New("whoops"))
client := dockerClient{api: api}
_, err := client.ListContainers(allContainers)
assert.Error(t, err)
assert.EqualError(t, err, "whoops")
api.AssertExpectations(t)
}
func TestStopContainer_DefaultSuccess(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Id: "abc123",
Config: &dockerclient.ContainerConfig{},
},
}
ci := &dockerclient.ContainerInfo{
State: &dockerclient.State{
Running: false,
},
}
api := mockclient.NewMockClient()
api.On("KillContainer", "abc123", "SIGTERM").Return(nil)
api.On("InspectContainer", "abc123").Return(ci, nil).Once()
api.On("RemoveContainer", "abc123", true, false).Return(nil)
api.On("InspectContainer", "abc123").Return(&dockerclient.ContainerInfo{}, errors.New("Not Found"))
client := dockerClient{api: api}
err := client.StopContainer(c, time.Second)
assert.NoError(t, err)
api.AssertExpectations(t)
}
func TestStopContainer_CustomSignalSuccess(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Id: "abc123",
Config: &dockerclient.ContainerConfig{
Labels: map[string]string{"com.centurylinklabs.watchtower.stop-signal": "SIGUSR1"}},
},
}
ci := &dockerclient.ContainerInfo{
State: &dockerclient.State{
Running: false,
},
}
api := mockclient.NewMockClient()
api.On("KillContainer", "abc123", "SIGUSR1").Return(nil)
api.On("InspectContainer", "abc123").Return(ci, nil).Once()
api.On("RemoveContainer", "abc123", true, false).Return(nil)
api.On("InspectContainer", "abc123").Return(&dockerclient.ContainerInfo{}, errors.New("Not Found"))
client := dockerClient{api: api}
err := client.StopContainer(c, time.Second)
assert.NoError(t, err)
api.AssertExpectations(t)
}
func TestStopContainer_KillContainerError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Id: "abc123",
Config: &dockerclient.ContainerConfig{},
},
}
api := mockclient.NewMockClient()
api.On("KillContainer", "abc123", "SIGTERM").Return(errors.New("oops"))
client := dockerClient{api: api}
err := client.StopContainer(c, time.Second)
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}
func TestStopContainer_RemoveContainerError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Id: "abc123",
Config: &dockerclient.ContainerConfig{},
},
}
api := mockclient.NewMockClient()
api.On("KillContainer", "abc123", "SIGTERM").Return(nil)
api.On("InspectContainer", "abc123").Return(&dockerclient.ContainerInfo{}, errors.New("dangit"))
api.On("RemoveContainer", "abc123", true, false).Return(errors.New("whoops"))
client := dockerClient{api: api}
err := client.StopContainer(c, time.Second)
assert.Error(t, err)
assert.EqualError(t, err, "whoops")
api.AssertExpectations(t)
}
func TestStartContainer_Success(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{},
HostConfig: &dockerclient.HostConfig{},
},
imageInfo: &dockerclient.ImageInfo{
Config: &dockerclient.ContainerConfig{},
},
}
api := mockclient.NewMockClient()
api.On("CreateContainer", mock.AnythingOfType("*dockerclient.ContainerConfig"), "foo").Return("def789", nil)
api.On("StartContainer", "def789", mock.AnythingOfType("*dockerclient.HostConfig")).Return(nil)
client := dockerClient{api: api}
err := client.StartContainer(c)
assert.NoError(t, err)
api.AssertExpectations(t)
}
func TestStartContainer_CreateContainerError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{},
HostConfig: &dockerclient.HostConfig{},
},
imageInfo: &dockerclient.ImageInfo{
Config: &dockerclient.ContainerConfig{},
},
}
api := mockclient.NewMockClient()
api.On("CreateContainer", mock.Anything, "foo").Return("", errors.New("oops"))
client := dockerClient{api: api}
err := client.StartContainer(c)
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}
func TestStartContainer_StartContainerError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{},
HostConfig: &dockerclient.HostConfig{},
},
imageInfo: &dockerclient.ImageInfo{
Config: &dockerclient.ContainerConfig{},
},
}
api := mockclient.NewMockClient()
api.On("CreateContainer", mock.Anything, "foo").Return("def789", nil)
api.On("StartContainer", "def789", mock.Anything).Return(errors.New("whoops"))
client := dockerClient{api: api}
err := client.StartContainer(c)
assert.Error(t, err)
assert.EqualError(t, err, "whoops")
api.AssertExpectations(t)
}
func TestRenameContainer_Success(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Id: "abc123",
},
}
api := mockclient.NewMockClient()
api.On("RenameContainer", "abc123", "foo").Return(nil)
client := dockerClient{api: api}
err := client.RenameContainer(c, "foo")
assert.NoError(t, err)
api.AssertExpectations(t)
}
func TestRenameContainer_Error(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Id: "abc123",
},
}
api := mockclient.NewMockClient()
api.On("RenameContainer", "abc123", "foo").Return(errors.New("oops"))
client := dockerClient{api: api}
err := client.RenameContainer(c, "foo")
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}
func TestIsContainerStale_NotStaleSuccess(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{Image: "bar"},
},
imageInfo: &dockerclient.ImageInfo{Id: "abc123"},
}
newImageInfo := &dockerclient.ImageInfo{Id: "abc123"}
api := mockclient.NewMockClient()
api.On("PullImage", "bar:latest", mock.Anything).Return(nil)
api.On("InspectImage", "bar:latest").Return(newImageInfo, nil)
client := dockerClient{api: api, pullImages: true}
stale, err := client.IsContainerStale(c)
assert.NoError(t, err)
assert.False(t, stale)
api.AssertExpectations(t)
}
func TestIsContainerStale_StaleSuccess(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{Image: "bar:1.0"},
},
imageInfo: &dockerclient.ImageInfo{Id: "abc123"},
}
newImageInfo := &dockerclient.ImageInfo{Id: "xyz789"}
api := mockclient.NewMockClient()
api.On("PullImage", "bar:1.0", mock.Anything).Return(nil)
api.On("InspectImage", "bar:1.0").Return(newImageInfo, nil)
client := dockerClient{api: api, pullImages: true}
stale, err := client.IsContainerStale(c)
assert.NoError(t, err)
assert.True(t, stale)
api.AssertExpectations(t)
}
func TestIsContainerStale_NoPullSuccess(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{Image: "bar:1.0"},
},
imageInfo: &dockerclient.ImageInfo{Id: "abc123"},
}
newImageInfo := &dockerclient.ImageInfo{Id: "xyz789"}
api := mockclient.NewMockClient()
api.On("InspectImage", "bar:1.0").Return(newImageInfo, nil)
client := dockerClient{api: api, pullImages: false}
stale, err := client.IsContainerStale(c)
assert.NoError(t, err)
assert.True(t, stale)
api.AssertExpectations(t)
}
func TestIsContainerStale_PullImageError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{Image: "bar:latest"},
},
imageInfo: &dockerclient.ImageInfo{Id: "abc123"},
}
api := mockclient.NewMockClient()
api.On("PullImage", "bar:latest", mock.Anything).Return(errors.New("oops"))
client := dockerClient{api: api, pullImages: true}
_, err := client.IsContainerStale(c)
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}
func TestIsContainerStale_InspectImageError(t *testing.T) {
c := Container{
containerInfo: &dockerclient.ContainerInfo{
Name: "foo",
Config: &dockerclient.ContainerConfig{Image: "bar:latest"},
},
imageInfo: &dockerclient.ImageInfo{Id: "abc123"},
}
newImageInfo := &dockerclient.ImageInfo{}
api := mockclient.NewMockClient()
api.On("PullImage", "bar:latest", mock.Anything).Return(nil)
api.On("InspectImage", "bar:latest").Return(newImageInfo, errors.New("uh-oh"))
client := dockerClient{api: api, pullImages: true}
_, err := client.IsContainerStale(c)
assert.Error(t, err)
assert.EqualError(t, err, "uh-oh")
api.AssertExpectations(t)
}
func TestRemoveImage_Success(t *testing.T) {
c := Container{
imageInfo: &dockerclient.ImageInfo{
Id: "abc123",
},
}
api := mockclient.NewMockClient()
api.On("RemoveImage", "abc123").Return([]*dockerclient.ImageDelete{}, nil)
client := dockerClient{api: api}
err := client.RemoveImage(c)
assert.NoError(t, err)
api.AssertExpectations(t)
}
func TestRemoveImage_Error(t *testing.T) {
c := Container{
imageInfo: &dockerclient.ImageInfo{
Id: "abc123",
},
}
api := mockclient.NewMockClient()
api.On("RemoveImage", "abc123").Return([]*dockerclient.ImageDelete{}, errors.New("oops"))
client := dockerClient{api: api}
err := client.RemoveImage(c)
assert.Error(t, err)
assert.EqualError(t, err, "oops")
api.AssertExpectations(t)
}