Added some tests for docker check

This commit is contained in:
Diptanu Choudhury 2015-10-26 12:59:40 -07:00
parent d478fa9470
commit f445318732
2 changed files with 154 additions and 6 deletions

View File

@ -502,6 +502,14 @@ func (c *CheckTCP) check() {
c.Notify.UpdateCheck(c.CheckID, structs.HealthPassing, fmt.Sprintf("TCP connect %s: Success", c.TCP))
}
// A custom interface since go-dockerclient doesn't have one
// We will use this interface in our test to inject a fake client
type DockerClient interface {
CreateExec(docker.CreateExecOptions) (*docker.Exec, error)
StartExec(string, docker.StartExecOptions) error
InspectExec(string) (*docker.ExecInspect, error)
}
// CheckDocker is used to periodically invoke a script to
// determine the health of an application running inside a
// Docker Container. We assume that the script is compatible
@ -515,8 +523,7 @@ type CheckDocker struct {
Interval time.Duration
Logger *log.Logger
dockerClient *docker.Client
exec *docker.Exec
dockerClient DockerClient
cmd []string
stop bool
stopCh chan struct{}
@ -530,10 +537,12 @@ func (c *CheckDocker) Start() {
defer c.stopLock.Unlock()
//create the docker client
var err error
c.dockerClient, err = docker.NewClientFromEnv()
if err != nil {
c.Logger.Println("[DEBUG] Error creating the Docker Client : %s", err.Error())
if c.dockerClient == nil {
var err error
c.dockerClient, err = docker.NewClientFromEnv()
if err != nil {
c.Logger.Println("[DEBUG] Error creating the Docker Client : %s", err.Error())
}
}
//figure out the shell

View File

@ -1,6 +1,7 @@
package agent
import (
"errors"
"fmt"
"log"
"net"
@ -10,6 +11,7 @@ import (
"testing"
"time"
docker "github.com/fsouza/go-dockerclient"
"github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/testutil"
)
@ -393,3 +395,140 @@ func TestCheckTCPPassing(t *testing.T) {
expectTCPStatus(t, tcpServer.Addr().String(), "passing")
tcpServer.Close()
}
// A fake docker client to test happy path scenario
type fakeDockerClientWithNoErrors struct {
}
func (d *fakeDockerClientWithNoErrors) CreateExec(opts docker.CreateExecOptions) (*docker.Exec, error) {
return &docker.Exec{ID: "123"}, nil
}
func (d *fakeDockerClientWithNoErrors) StartExec(id string, opts docker.StartExecOptions) error {
return nil
}
func (d *fakeDockerClientWithNoErrors) InspectExec(id string) (*docker.ExecInspect, error) {
return &docker.ExecInspect{
ID: "123",
ExitCode: 0,
}, nil
}
// A fake docker client to test non-zero exit codes from exec invocation
type fakeDockerClientWithExecNonZeroExitCode struct {
}
func (d *fakeDockerClientWithExecNonZeroExitCode) CreateExec(opts docker.CreateExecOptions) (*docker.Exec, error) {
return &docker.Exec{ID: "123"}, nil
}
func (d *fakeDockerClientWithExecNonZeroExitCode) StartExec(id string, opts docker.StartExecOptions) error {
return nil
}
func (d *fakeDockerClientWithExecNonZeroExitCode) InspectExec(id string) (*docker.ExecInspect, error) {
return &docker.ExecInspect{
ID: "123",
ExitCode: 127,
}, nil
}
// A fake docker client to simulate create exec failing
type fakeDockerClientWithCreateExecFailure struct {
}
func (d *fakeDockerClientWithCreateExecFailure) CreateExec(opts docker.CreateExecOptions) (*docker.Exec, error) {
return nil, errors.New("Exec Creation Failed")
}
func (d *fakeDockerClientWithCreateExecFailure) StartExec(id string, opts docker.StartExecOptions) error {
return errors.New("Exec doesn't exist")
}
func (d *fakeDockerClientWithCreateExecFailure) InspectExec(id string) (*docker.ExecInspect, error) {
return nil, errors.New("Exec doesn't exist")
}
// A fake docker client to simulate start exec failing
type fakeDockerClientWithStartExecFailure struct {
}
func (d *fakeDockerClientWithStartExecFailure) CreateExec(opts docker.CreateExecOptions) (*docker.Exec, error) {
return &docker.Exec{ID: "123"}, nil
}
func (d *fakeDockerClientWithStartExecFailure) StartExec(id string, opts docker.StartExecOptions) error {
return nil
}
func (d *fakeDockerClientWithStartExecFailure) InspectExec(id string) (*docker.ExecInspect, error) {
return nil, errors.New("Exec doesn't exist")
}
// A fake docker client to test exec info query failures
type fakeDockerClientWithExecInfoErrors struct {
}
func (d *fakeDockerClientWithExecInfoErrors) CreateExec(opts docker.CreateExecOptions) (*docker.Exec, error) {
return &docker.Exec{ID: "123"}, nil
}
func (d *fakeDockerClientWithExecInfoErrors) StartExec(id string, opts docker.StartExecOptions) error {
return nil
}
func (d *fakeDockerClientWithExecInfoErrors) InspectExec(id string) (*docker.ExecInspect, error) {
return nil, errors.New("Unable to query exec info")
}
func expectDockerCheckStatus(t *testing.T, dockerClient DockerClient, status string) {
mock := &MockNotify{
state: make(map[string]string),
updates: make(map[string]int),
output: make(map[string]string),
}
check := &CheckDocker{
Notify: mock,
CheckID: "foo",
Script: "/health.sh",
DockerContainerId: "54432bad1fc7",
Shell: "/bin/sh",
Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags),
dockerClient: dockerClient,
}
check.Start()
defer check.Stop()
time.Sleep(50 * time.Millisecond)
// Should have at least 2 updates
if mock.updates["foo"] < 2 {
t.Fatalf("should have 2 updates %v", mock.updates)
}
if mock.state["foo"] != status {
t.Fatalf("should be %v %v", status, mock.state)
}
}
func TestDockerCheckWhenExecReturnsSuccessExitCode(t *testing.T) {
expectDockerCheckStatus(t, &fakeDockerClientWithNoErrors{}, "passing")
}
func TestDockerCheckWhenExecCreationFails(t *testing.T) {
expectDockerCheckStatus(t, &fakeDockerClientWithCreateExecFailure{}, "critical")
}
func TestDockerCheckWhenExitCodeIsNonZero(t *testing.T) {
expectDockerCheckStatus(t, &fakeDockerClientWithExecNonZeroExitCode{}, "critical")
}
func TestDockerCheckWhenExecStartFails(t *testing.T) {
expectDockerCheckStatus(t, &fakeDockerClientWithStartExecFailure{}, "critical")
}
func TestDockerCheckWhenExecInfoFails(t *testing.T) {
expectDockerCheckStatus(t, &fakeDockerClientWithExecInfoErrors{}, "critical")
}