Skip to content

Commit bdefb2c

Browse files
authored
Check for agent rogue processes in integration tests (#4225)
* Check for agent rogue processes in integration tests This commit adds assertions at the beginning and at the end of Fixture.Install() checking that no agent processes are running before installing or after uninstalling. If any elastic-agent processes are detected, the test is marked as failed but it still runs to completion.
1 parent 51e8456 commit bdefb2c

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

pkg/testing/fixture_install.go

+84
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ import (
1616
"runtime"
1717
"strconv"
1818
"strings"
19+
gotesting "testing"
1920
"time"
2021

22+
"github.com/stretchr/testify/assert"
2123
"github.com/stretchr/testify/require"
2224

25+
"github.com/elastic/elastic-agent-libs/mapstr"
26+
"github.com/elastic/elastic-agent-libs/opt"
27+
agentsystemprocess "github.com/elastic/elastic-agent-system-metrics/metric/system/process"
2328
"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
2429
"github.com/elastic/elastic-agent/pkg/control/v2/client"
2530
"github.com/elastic/elastic-agent/pkg/core/process"
@@ -123,6 +128,10 @@ func NewBool(value bool) *bool {
123128
// - an error if any.
124129
func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ...process.CmdOption) ([]byte, error) {
125130
f.t.Logf("[test %s] Inside fixture install function", f.t.Name())
131+
132+
// check for running agents before installing
133+
assert.Empty(f.t, getElasticAgentProcesses(f.t), "there should be no running agent at beginning of Install()")
134+
126135
installArgs := []string{"install"}
127136
if installOpts == nil {
128137
// default options when not provided
@@ -161,8 +170,14 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
161170
c := client.New(client.WithAddress(socketPath))
162171
f.setClient(c)
163172

173+
f.t.Cleanup(func() {
174+
// check for running agents after uninstall had a chance to run
175+
assert.Empty(f.t, getElasticAgentProcesses(f.t), "there should be no running agent at the end of the test")
176+
})
177+
164178
f.t.Cleanup(func() {
165179
f.t.Logf("[test %s] Inside fixture cleanup function", f.t.Name())
180+
166181
if !f.installed {
167182
f.t.Logf("skipping uninstall; agent not installed (fixture.installed is false)")
168183
// not installed; no need to clean up or collect diagnostics
@@ -218,6 +233,75 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
218233
return out, nil
219234
}
220235

236+
type runningProcess struct {
237+
// Basic Process data
238+
Name string
239+
State agentsystemprocess.PidState
240+
Username string
241+
Pid opt.Int
242+
Ppid opt.Int
243+
Pgid opt.Int
244+
245+
// Extended Process Data
246+
Args []string
247+
Cmdline string
248+
Cwd string
249+
Exe string
250+
Env mapstr.M
251+
}
252+
253+
func (p runningProcess) String() string {
254+
return fmt.Sprintf("{PID:%v, PPID: %v, Cwd: %s, Exe: %s, Cmdline: %s, Args: %v}",
255+
p.Pid, p.Ppid, p.Cwd, p.Exe, p.Cmdline, p.Args)
256+
}
257+
258+
func mapProcess(p agentsystemprocess.ProcState) runningProcess {
259+
mappedProcess := runningProcess{
260+
Name: p.Name,
261+
State: p.State,
262+
Username: p.Username,
263+
Pid: p.Pid,
264+
Ppid: p.Ppid,
265+
Pgid: p.Pgid,
266+
Cmdline: p.Cmdline,
267+
Cwd: p.Cwd,
268+
Exe: p.Exe,
269+
Args: make([]string, len(p.Args)),
270+
Env: make(mapstr.M),
271+
}
272+
copy(mappedProcess.Args, p.Args)
273+
for k, v := range p.Env {
274+
mappedProcess.Env[k] = v
275+
}
276+
return mappedProcess
277+
}
278+
279+
func getElasticAgentProcesses(t *gotesting.T) []runningProcess {
280+
procStats := agentsystemprocess.Stats{
281+
Procs: []string{`.*elastic\-agent.*`},
282+
}
283+
284+
err := procStats.Init()
285+
if !assert.NoError(t, err, "error initializing process.Stats") {
286+
// we failed
287+
return nil
288+
}
289+
290+
_, pids, err := procStats.FetchPids()
291+
if !assert.NoError(t, err, "error fetching process information") {
292+
// we failed a bit further
293+
return nil
294+
}
295+
296+
processes := make([]runningProcess, 0, len(pids))
297+
298+
for _, p := range pids {
299+
processes = append(processes, mapProcess(p))
300+
}
301+
302+
return processes
303+
}
304+
221305
type UninstallOpts struct {
222306
Force bool // --force
223307
UninstallToken string

0 commit comments

Comments
 (0)