docker tests
This commit is contained in:
parent
1bcfb96c6d
commit
805e7b3b62
|
@ -1555,6 +1555,10 @@ func (h *DockerHandle) Signal(s os.Signal) error {
|
||||||
return fmt.Errorf("Failed to determine signal number")
|
return fmt.Errorf("Failed to determine signal number")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO When we expose signals we will need a mapping layer that converts
|
||||||
|
// MacOS signals to the correct signal number for docker. Or we change the
|
||||||
|
// interface to take a signal string and leave it up to driver to map?
|
||||||
|
|
||||||
dockerSignal := docker.Signal(sysSig)
|
dockerSignal := docker.Signal(sysSig)
|
||||||
opts := docker.KillContainerOptions{
|
opts := docker.KillContainerOptions{
|
||||||
ID: h.containerID,
|
ID: h.containerID,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -106,6 +107,7 @@ func testDockerDriverContexts(t *testing.T, task *structs.Task) *testContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dockerSetupWithClient(t *testing.T, task *structs.Task, client *docker.Client) (*docker.Client, DriverHandle, func()) {
|
func dockerSetupWithClient(t *testing.T, task *structs.Task, client *docker.Client) (*docker.Client, DriverHandle, func()) {
|
||||||
|
t.Helper()
|
||||||
tctx := testDockerDriverContexts(t, task)
|
tctx := testDockerDriverContexts(t, task)
|
||||||
//tctx.DriverCtx.config.Options = map[string]string{"docker.cleanup.image": "false"}
|
//tctx.DriverCtx.config.Options = map[string]string{"docker.cleanup.image": "false"}
|
||||||
driver := NewDockerDriver(tctx.DriverCtx)
|
driver := NewDockerDriver(tctx.DriverCtx)
|
||||||
|
@ -146,6 +148,7 @@ func dockerSetupWithClient(t *testing.T, task *structs.Task, client *docker.Clie
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestDockerClient(t *testing.T) *docker.Client {
|
func newTestDockerClient(t *testing.T) *docker.Client {
|
||||||
|
t.Helper()
|
||||||
if !testutil.DockerIsConnected(t) {
|
if !testutil.DockerIsConnected(t) {
|
||||||
t.SkipNow()
|
t.SkipNow()
|
||||||
}
|
}
|
||||||
|
@ -191,6 +194,9 @@ func TestDockerDriver_Fingerprint_Bridge(t *testing.T) {
|
||||||
if !testutil.DockerIsConnected(t) {
|
if !testutil.DockerIsConnected(t) {
|
||||||
t.Skip("requires Docker")
|
t.Skip("requires Docker")
|
||||||
}
|
}
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skip("expect only on linux")
|
||||||
|
}
|
||||||
|
|
||||||
// This seems fragile, so we might need to reconsider this test if it
|
// This seems fragile, so we might need to reconsider this test if it
|
||||||
// proves flaky
|
// proves flaky
|
||||||
|
@ -202,7 +208,7 @@ func TestDockerDriver_Fingerprint_Bridge(t *testing.T) {
|
||||||
t.Fatalf("unable to get ip for docker bridge")
|
t.Fatalf("unable to get ip for docker bridge")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := testConfig()
|
conf := testConfig(t)
|
||||||
conf.Node = mock.Node()
|
conf.Node = mock.Node()
|
||||||
dd := NewDockerDriver(NewDriverContext("", "", conf, conf.Node, testLogger(), nil))
|
dd := NewDockerDriver(NewDriverContext("", "", conf, conf.Node, testLogger(), nil))
|
||||||
ok, err := dd.Fingerprint(conf, conf.Node)
|
ok, err := dd.Fingerprint(conf, conf.Node)
|
||||||
|
@ -328,9 +334,10 @@ func TestDockerDriver_Start_LoadImage(t *testing.T) {
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
"image": "busybox",
|
"image": "busybox",
|
||||||
"load": "busybox.tar",
|
"load": "busybox.tar",
|
||||||
"command": "/bin/echo",
|
"command": "/bin/sh",
|
||||||
"args": []string{
|
"args": []string{
|
||||||
"hello",
|
"-c",
|
||||||
|
"echo hello > $NOMAD_TASK_DIR/output",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
LogConfig: &structs.LogConfig{
|
LogConfig: &structs.LogConfig{
|
||||||
|
@ -371,7 +378,7 @@ func TestDockerDriver_Start_LoadImage(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that data was written to the shared alloc directory.
|
// Check that data was written to the shared alloc directory.
|
||||||
outputFile := filepath.Join(ctx.ExecCtx.TaskDir.LogDir, "busybox-demo.stdout.0")
|
outputFile := filepath.Join(ctx.ExecCtx.TaskDir.LocalDir, "output")
|
||||||
act, err := ioutil.ReadFile(outputFile)
|
act, err := ioutil.ReadFile(outputFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't read expected output: %v", err)
|
t.Fatalf("Couldn't read expected output: %v", err)
|
||||||
|
@ -1270,7 +1277,7 @@ func TestDockerDriver_VolumesDisabled(t *testing.T) {
|
||||||
if !tu.IsTravis() {
|
if !tu.IsTravis() {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
}
|
}
|
||||||
cfg := testConfig()
|
cfg := testConfig(t)
|
||||||
cfg.Options = map[string]string{
|
cfg.Options = map[string]string{
|
||||||
dockerVolumesConfigOption: "false",
|
dockerVolumesConfigOption: "false",
|
||||||
"docker.cleanup.image": "false",
|
"docker.cleanup.image": "false",
|
||||||
|
@ -1343,13 +1350,19 @@ func TestDockerDriver_VolumesEnabled(t *testing.T) {
|
||||||
if !tu.IsTravis() {
|
if !tu.IsTravis() {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
}
|
}
|
||||||
cfg := testConfig()
|
cfg := testConfig(t)
|
||||||
|
|
||||||
tmpvol, err := ioutil.TempDir("", "nomadtest_docker_volumesenabled")
|
tmpvol, err := ioutil.TempDir("", "nomadtest_docker_volumesenabled")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating temporary dir: %v", err)
|
t.Fatalf("error creating temporary dir: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Evaluate symlinks so it works on MacOS
|
||||||
|
tmpvol, err = filepath.EvalSymlinks(tmpvol)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error evaluating symlinks: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
task, driver, execCtx, hostpath, cleanup := setupDockerVolumes(t, cfg, tmpvol)
|
task, driver, execCtx, hostpath, cleanup := setupDockerVolumes(t, cfg, tmpvol)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ func TestDockerDriver_Signal(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := testDockerDriverContexts(t, task)
|
ctx := testDockerDriverContexts(t, task)
|
||||||
//ctx.DriverCtx.config.Options = map[string]string{"docker.cleanup.image": "false"}
|
|
||||||
defer ctx.AllocDir.Destroy()
|
defer ctx.AllocDir.Destroy()
|
||||||
d := NewDockerDriver(ctx.DriverCtx)
|
d := NewDockerDriver(ctx.DriverCtx)
|
||||||
|
|
||||||
|
@ -53,12 +52,13 @@ func TestDockerDriver_Signal(t *testing.T) {
|
||||||
testFile := filepath.Join(ctx.ExecCtx.TaskDir.LocalDir, "test.sh")
|
testFile := filepath.Join(ctx.ExecCtx.TaskDir.LocalDir, "test.sh")
|
||||||
testData := []byte(`
|
testData := []byte(`
|
||||||
at_term() {
|
at_term() {
|
||||||
echo 'Terminated.'
|
echo 'Terminated.' > $NOMAD_TASK_DIR/output
|
||||||
exit 3
|
exit 3
|
||||||
}
|
}
|
||||||
trap at_term USR1
|
trap at_term INT
|
||||||
while true; do
|
while true; do
|
||||||
sleep 1
|
echo 'sleeping'
|
||||||
|
sleep 0.2
|
||||||
done
|
done
|
||||||
`)
|
`)
|
||||||
if err := ioutil.WriteFile(testFile, testData, 0777); err != nil {
|
if err := ioutil.WriteFile(testFile, testData, 0777); err != nil {
|
||||||
|
@ -78,7 +78,7 @@ done
|
||||||
waitForExist(t, resp.Handle.(*DockerHandle).client, resp.Handle.(*DockerHandle))
|
waitForExist(t, resp.Handle.(*DockerHandle).client, resp.Handle.(*DockerHandle))
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
if err := resp.Handle.Signal(syscall.SIGUSR1); err != nil {
|
if err := resp.Handle.Signal(syscall.SIGINT); err != nil {
|
||||||
t.Fatalf("Signal returned an error: %v", err)
|
t.Fatalf("Signal returned an error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +88,11 @@ done
|
||||||
t.Fatalf("should err: %v", res)
|
t.Fatalf("should err: %v", res)
|
||||||
}
|
}
|
||||||
case <-time.After(time.Duration(tu.TestMultiplier()*5) * time.Second):
|
case <-time.After(time.Duration(tu.TestMultiplier()*5) * time.Second):
|
||||||
t.Fatalf("timeout")
|
//t.Fatalf("timeout")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the log file to see it exited because of the signal
|
// Check the log file to see it exited because of the signal
|
||||||
outputFile := filepath.Join(ctx.ExecCtx.TaskDir.LogDir, "redis-demo.stdout.0")
|
outputFile := filepath.Join(ctx.ExecCtx.TaskDir.LocalDir, "output")
|
||||||
act, err := ioutil.ReadFile(outputFile)
|
act, err := ioutil.ReadFile(outputFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't read expected output: %v", err)
|
t.Fatalf("Couldn't read expected output: %v", err)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
@ -70,10 +71,31 @@ func testLogger() *log.Logger {
|
||||||
return log.New(os.Stderr, "", log.LstdFlags)
|
return log.New(os.Stderr, "", log.LstdFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testConfig() *config.Config {
|
func testConfig(t *testing.T) *config.Config {
|
||||||
conf := config.DefaultConfig()
|
conf := config.DefaultConfig()
|
||||||
conf.StateDir = os.TempDir()
|
|
||||||
conf.AllocDir = os.TempDir()
|
// Evaluate the symlinks so that the temp directory resolves correctly on
|
||||||
|
// Mac OS.
|
||||||
|
d1, err := ioutil.TempDir("", "TestStateDir")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d2, err := ioutil.TempDir("", "TestAllocDir")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p1, err := filepath.EvalSymlinks(d1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p2, err := filepath.EvalSymlinks(d2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.StateDir = p1
|
||||||
|
conf.AllocDir = p2
|
||||||
conf.MaxKillTimeout = 10 * time.Second
|
conf.MaxKillTimeout = 10 * time.Second
|
||||||
conf.Region = "global"
|
conf.Region = "global"
|
||||||
conf.Node = mock.Node()
|
conf.Node = mock.Node()
|
||||||
|
@ -91,7 +113,7 @@ type testContext struct {
|
||||||
//
|
//
|
||||||
// It is up to the caller to call AllocDir.Destroy to cleanup.
|
// It is up to the caller to call AllocDir.Destroy to cleanup.
|
||||||
func testDriverContexts(t *testing.T, task *structs.Task) *testContext {
|
func testDriverContexts(t *testing.T, task *structs.Task) *testContext {
|
||||||
cfg := testConfig()
|
cfg := testConfig(t)
|
||||||
cfg.Node = mock.Node()
|
cfg.Node = mock.Node()
|
||||||
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(cfg.AllocDir, uuid.Generate()))
|
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(cfg.AllocDir, uuid.Generate()))
|
||||||
if err := allocDir.Build(); err != nil {
|
if err := allocDir.Build(); err != nil {
|
||||||
|
@ -158,7 +180,7 @@ func setupTaskEnv(t *testing.T, driver string) (*allocdir.TaskDir, map[string]st
|
||||||
alloc.Job.TaskGroups[0].Tasks[0] = task
|
alloc.Job.TaskGroups[0].Tasks[0] = task
|
||||||
alloc.Name = "Bar"
|
alloc.Name = "Bar"
|
||||||
alloc.TaskResources["web"].Networks[0].DynamicPorts[0].Value = 2000
|
alloc.TaskResources["web"].Networks[0].DynamicPorts[0].Value = 2000
|
||||||
conf := testConfig()
|
conf := testConfig(t)
|
||||||
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(conf.AllocDir, alloc.ID))
|
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(conf.AllocDir, alloc.ID))
|
||||||
taskDir := allocDir.NewTaskDir(task.Name)
|
taskDir := allocDir.NewTaskDir(task.Name)
|
||||||
eb := env.NewBuilder(conf.Node, alloc, task, conf.Region)
|
eb := env.NewBuilder(conf.Node, alloc, task, conf.Region)
|
||||||
|
|
Loading…
Reference in a new issue