github.com/taylorchu/nomad@v0.5.3-rc1.0.20170407200202-db11e7dd7b55/client/driver/exec_unix_test.go (about) 1 // +build !windows 2 3 package driver 4 5 import ( 6 "encoding/json" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "syscall" 12 "testing" 13 "time" 14 15 "github.com/hashicorp/nomad/nomad/structs" 16 "github.com/hashicorp/nomad/testutil" 17 18 ctestutils "github.com/hashicorp/nomad/client/testutil" 19 ) 20 21 func TestExecDriver_KillUserPid_OnPluginReconnectFailure(t *testing.T) { 22 ctestutils.ExecCompatible(t) 23 task := &structs.Task{ 24 Name: "sleep", 25 Driver: "exec", 26 Config: map[string]interface{}{ 27 "command": "/bin/sleep", 28 "args": []string{"1000000"}, 29 }, 30 LogConfig: &structs.LogConfig{ 31 MaxFiles: 10, 32 MaxFileSizeMB: 10, 33 }, 34 Resources: basicResources, 35 } 36 37 ctx := testDriverContexts(t, task) 38 defer ctx.AllocDir.Destroy() 39 d := NewExecDriver(ctx.DriverCtx) 40 41 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 42 t.Fatalf("prestart err: %v", err) 43 } 44 handle, err := d.Start(ctx.ExecCtx, task) 45 if err != nil { 46 t.Fatalf("err: %v", err) 47 } 48 if handle == nil { 49 t.Fatalf("missing handle") 50 } 51 defer handle.Kill() 52 53 id := &execId{} 54 if err := json.Unmarshal([]byte(handle.ID()), id); err != nil { 55 t.Fatalf("Failed to parse handle '%s': %v", handle.ID(), err) 56 } 57 pluginPid := id.PluginConfig.Pid 58 proc, err := os.FindProcess(pluginPid) 59 if err != nil { 60 t.Fatalf("can't find plugin pid: %v", pluginPid) 61 } 62 if err := proc.Kill(); err != nil { 63 t.Fatalf("can't kill plugin pid: %v", err) 64 } 65 66 // Attempt to open 67 handle2, err := d.Open(ctx.ExecCtx, handle.ID()) 68 if err == nil { 69 t.Fatalf("expected error") 70 } 71 if handle2 != nil { 72 handle2.Kill() 73 t.Fatalf("expected handle2 to be nil") 74 } 75 76 // Test if the userpid is still present 77 userProc, _ := os.FindProcess(id.UserPid) 78 79 for retry := 3; retry > 0; retry-- { 80 if err = userProc.Signal(syscall.Signal(0)); err != nil { 81 // Process is gone as expected; exit 82 return 83 } 84 85 // Killing processes is async; wait and check again 86 time.Sleep(time.Second) 87 } 88 if err = userProc.Signal(syscall.Signal(0)); err == nil { 89 t.Fatalf("expected user process to die") 90 } 91 } 92 93 func TestExecDriver_Signal(t *testing.T) { 94 ctestutils.ExecCompatible(t) 95 task := &structs.Task{ 96 Name: "signal", 97 Driver: "exec", 98 Config: map[string]interface{}{ 99 "command": "/bin/bash", 100 "args": []string{"test.sh"}, 101 }, 102 LogConfig: &structs.LogConfig{ 103 MaxFiles: 10, 104 MaxFileSizeMB: 10, 105 }, 106 Resources: basicResources, 107 KillTimeout: 10 * time.Second, 108 } 109 110 ctx := testDriverContexts(t, task) 111 defer ctx.AllocDir.Destroy() 112 d := NewExecDriver(ctx.DriverCtx) 113 114 testFile := filepath.Join(ctx.ExecCtx.TaskDir.Dir, "test.sh") 115 testData := []byte(` 116 at_term() { 117 echo 'Terminated.' 118 exit 3 119 } 120 trap at_term USR1 121 while true; do 122 sleep 1 123 done 124 `) 125 if err := ioutil.WriteFile(testFile, testData, 0777); err != nil { 126 t.Fatalf("Failed to write data: %v", err) 127 } 128 129 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 130 t.Fatalf("prestart err: %v", err) 131 } 132 handle, err := d.Start(ctx.ExecCtx, task) 133 if err != nil { 134 t.Fatalf("err: %v", err) 135 } 136 if handle == nil { 137 t.Fatalf("missing handle") 138 } 139 140 go func() { 141 time.Sleep(100 * time.Millisecond) 142 err := handle.Signal(syscall.SIGUSR1) 143 if err != nil { 144 t.Fatalf("err: %v", err) 145 } 146 }() 147 148 // Task should terminate quickly 149 select { 150 case res := <-handle.WaitCh(): 151 if res.Successful() { 152 t.Fatal("should err") 153 } 154 case <-time.After(time.Duration(testutil.TestMultiplier()*6) * time.Second): 155 t.Fatalf("timeout") 156 } 157 158 // Check the log file to see it exited because of the signal 159 outputFile := filepath.Join(ctx.ExecCtx.TaskDir.LogDir, "signal.stdout.0") 160 act, err := ioutil.ReadFile(outputFile) 161 if err != nil { 162 t.Fatalf("Couldn't read expected output: %v", err) 163 } 164 165 exp := "Terminated." 166 if strings.TrimSpace(string(act)) != exp { 167 t.Logf("Read from %v", outputFile) 168 t.Fatalf("Command outputted %v; want %v", act, exp) 169 } 170 }