|
|
|
|
@ -92,6 +92,9 @@ func TestContainerBoot(t *testing.T) {
|
|
|
|
|
// The signal to send to containerboot at the start of the phase.
|
|
|
|
|
Signal *syscall.Signal
|
|
|
|
|
|
|
|
|
|
// If set, send this signal to the fake tailscaled process.
|
|
|
|
|
SignalTailscaled *syscall.Signal
|
|
|
|
|
|
|
|
|
|
EndpointStatuses map[string]int
|
|
|
|
|
}
|
|
|
|
|
runningNotify := &ipn.Notify{
|
|
|
|
|
@ -993,6 +996,29 @@ func TestContainerBoot(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"tailscaled_unexpected_exit": func(env *testEnv) testCase {
|
|
|
|
|
return testCase{
|
|
|
|
|
Env: map[string]string{
|
|
|
|
|
"TS_AUTHKEY": "tskey-key",
|
|
|
|
|
},
|
|
|
|
|
Phases: []phase{
|
|
|
|
|
{
|
|
|
|
|
WantCmds: []string{
|
|
|
|
|
"/usr/bin/tailscaled --socket=/tmp/tailscaled.sock --state=mem: --statedir=/tmp --tun=userspace-networking",
|
|
|
|
|
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false --authkey=tskey-key",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Notify: runningNotify,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
SignalTailscaled: ptr.To(unix.SIGKILL),
|
|
|
|
|
WantLog: "tailscaled exited unexpectedly with code 137",
|
|
|
|
|
WantExitCode: ptr.To(1),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"kube_shutdown_during_state_write": func(env *testEnv) testCase {
|
|
|
|
|
return testCase{
|
|
|
|
|
Env: map[string]string{
|
|
|
|
|
@ -1103,6 +1129,9 @@ func TestContainerBoot(t *testing.T) {
|
|
|
|
|
if p.Signal != nil {
|
|
|
|
|
cmd.Process.Signal(*p.Signal)
|
|
|
|
|
}
|
|
|
|
|
if p.SignalTailscaled != nil {
|
|
|
|
|
signalTailscaled(t, env.d, *p.SignalTailscaled)
|
|
|
|
|
}
|
|
|
|
|
if p.WantLog != "" {
|
|
|
|
|
err := tstest.WaitFor(2*time.Second, func() error {
|
|
|
|
|
waitLogLine(t, time.Second, cbOut, p.WantLog)
|
|
|
|
|
@ -1586,6 +1615,44 @@ func egressSvcConfig(name, fqdn string) egressservices.Configs {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// signalTailscaled reads the PID of the fake tailscaled process and sends it a signal.
|
|
|
|
|
func signalTailscaled(t *testing.T, rootDir string, sig syscall.Signal) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
pidFile := filepath.Join(rootDir, "tmp/tailscaled.pid")
|
|
|
|
|
|
|
|
|
|
// Wait for PID file to exist (tailscaled may not have written it yet).
|
|
|
|
|
var pidBytes []byte
|
|
|
|
|
var err error
|
|
|
|
|
deadline := time.Now().Add(2 * time.Second)
|
|
|
|
|
for time.Now().Before(deadline) {
|
|
|
|
|
pidBytes, err = os.ReadFile(pidFile)
|
|
|
|
|
if err == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if !errors.Is(err, fs.ErrNotExist) {
|
|
|
|
|
t.Fatalf("reading tailscaled PID: %v", err)
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("tailscaled PID file never appeared: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pid, err := strconv.Atoi(strings.TrimSpace(string(pidBytes)))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("parsing tailscaled PID %q: %v", string(pidBytes), err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc, err := os.FindProcess(pid)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("finding tailscaled process %d: %v", pid, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := proc.Signal(sig); err != nil {
|
|
|
|
|
t.Fatalf("signaling tailscaled with %v: %v", sig, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// testEnv represents the environment needed for a single sub-test so that tests
|
|
|
|
|
// can run in parallel.
|
|
|
|
|
type testEnv struct {
|
|
|
|
|
|