diff --git a/agent/proxy/manager.go b/agent/proxy/manager.go index 7ed278037..f5c2d996e 100644 --- a/agent/proxy/manager.go +++ b/agent/proxy/manager.go @@ -354,11 +354,14 @@ func (m *Manager) newProxy(mp *local.ManagedProxy) (Proxy, error) { return nil, fmt.Errorf("daemon mode managed proxy requires command") } + // We reuse the service ID a few times + id := p.ProxyService.ID + // Build the command to execute. var cmd exec.Cmd cmd.Path = command[0] cmd.Args = command // idx 0 is path but preserved since it should be - if err := m.configureLogDir(p.ProxyService.ID, &cmd); err != nil { + if err := m.configureLogDir(id, &cmd); err != nil { return nil, fmt.Errorf("error configuring proxy logs: %s", err) } @@ -367,6 +370,7 @@ func (m *Manager) newProxy(mp *local.ManagedProxy) (Proxy, error) { Command: &cmd, ProxyToken: mp.ProxyToken, Logger: m.Logger, + PidPath: pidPath(filepath.Join(m.DataDir, "pids"), id), }, nil default: @@ -414,3 +418,14 @@ func (m *Manager) configureLogDir(id string, cmd *exec.Cmd) error { func logPath(dir, id, stream string) string { return filepath.Join(dir, fmt.Sprintf("%s-%s.log", id, stream)) } + +// pidPath is a helper to return the path to the pid file for the given +// directory and service ID. +func pidPath(dir, id string) string { + // If no directory is given we do not write a pid + if dir == "" { + return "" + } + + return filepath.Join(dir, fmt.Sprintf("%s.pid", id)) +} diff --git a/agent/proxy/manager_test.go b/agent/proxy/manager_test.go index d14b71afa..d9a817af3 100644 --- a/agent/proxy/manager_test.go +++ b/agent/proxy/manager_test.go @@ -227,6 +227,40 @@ func TestManagerRun_daemonLogs(t *testing.T) { require.Equal([]byte(expectedErr), actual) } +func TestManagerRun_daemonPid(t *testing.T) { + t.Parallel() + + require := require.New(t) + state := local.TestState(t) + m, closer := testManager(t) + defer closer() + m.State = state + defer m.Kill() + + // Configure a log dir so that we can read the logs + pidDir := filepath.Join(m.DataDir, "pids") + + // Create the service and calculate the log paths + path := filepath.Join(m.DataDir, "notify") + id := testStateProxy(t, state, "web", helperProcess("output", path)) + pidPath := pidPath(pidDir, id) + + // Start the manager + go m.Run() + + // We should see the path appear shortly + retry.Run(t, func(r *retry.R) { + if _, err := os.Stat(path); err != nil { + r.Fatalf("error waiting for stdout path: %s", err) + } + }) + + // Verify the pid file is not empty + pidRaw, err := ioutil.ReadFile(pidPath) + require.NoError(err) + require.NotEmpty(pidRaw) +} + func testManager(t *testing.T) (*Manager, func()) { m := NewManager()