-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix input reload under Elastic-Agent #35250
Changes from 43 commits
68df822
7fce900
4d0732b
37cfef3
2ba009a
66176c8
b31bd28
c902ab8
dd0a47e
0b36d19
71bd239
4d2e32d
a1ac3bb
b149c85
dda54d9
d3e45a2
091dd31
e65618b
b3028a7
78930f0
0049bd1
ea5d84f
f12f5e9
cff80ed
04a87d0
3a299a6
2424579
892e4ed
5f44afb
c153d74
12a0ba5
a677530
1ffe0b6
dc147b1
9ea251a
4c2fcd7
f1bf065
0f67fb2
c6a74e9
efd1811
49f314d
e9ce324
d36f486
a98f0a9
8eece56
844194a
a37a275
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
//go:build integration | ||
|
||
package integration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file is the beginning of a integration tests framework in Go, much like our current Python system tests. I kept it very simple and only implemented the bare minimum to write tests for this PR, hence it's not even on its own package. Whenever we need to use on a different test we can extract it into another package and improve it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a particular reason to put it under the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, all Elastic-Agent related code is here, which includes the manager who will interact with this "framework". Even it it is outside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file doesn't look like it depends on anything that is x-pack licensed, but the test itself definitely does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider moving this to an Apache license out of the x-pack directory so it can be reused by the OSS parts of Beats. |
||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"io" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"strings" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
type BeatProc struct { | ||
Binary string | ||
Args []string | ||
Cmd *exec.Cmd | ||
t *testing.T | ||
tempDir string | ||
} | ||
|
||
// NewBeat createa a new Beat process from the system tests binary. | ||
// It sets some required options like the home path, logging, etc. | ||
// `tempDir` will be used as home and logs directory for the Beat | ||
// `args` will be passed as CLI arguments to the Beat | ||
func NewBeat(t *testing.T, binary string, tempDir string, args ...string) BeatProc { | ||
p := BeatProc{ | ||
t: t, | ||
Binary: binary, | ||
Args: append([]string{ | ||
"--systemTest", | ||
"--path.home", tempDir, | ||
"--path.logs", tempDir, | ||
"-E", "logging.to_files=true", | ||
"-E", "logging.files.rotateeverybytes=104857600", // About 100MB | ||
}, args...), | ||
tempDir: tempDir, | ||
} | ||
return p | ||
} | ||
|
||
// Start starts the Beat process | ||
func (b *BeatProc) Start() { | ||
t := b.t | ||
fullPath, err := filepath.Abs(b.Binary) | ||
if err != nil { | ||
t.Fatalf("could not get full path from %q, err: %s", b.Binary, err) | ||
} | ||
b.Cmd = exec.Command(fullPath, b.Args...) | ||
|
||
if err := b.Cmd.Start(); err != nil { | ||
t.Fatalf("could not start process: %s", err) | ||
} | ||
t.Cleanup(func() { | ||
pid := b.Cmd.Process.Pid | ||
if err := b.Cmd.Process.Kill(); err != nil { | ||
t.Fatalf("could not stop process with PID: %d, err: %s", pid, err) | ||
} | ||
}) | ||
} | ||
|
||
// LogContains looks for `s` as a substring of every log line, | ||
// it will open the log file on every call, read it until EOF, | ||
// then close it. | ||
func (b *BeatProc) LogContains(s string) bool { | ||
t := b.t | ||
logFile := b.openLogFile() | ||
defer func() { | ||
if err := logFile.Close(); err != nil { | ||
// That's not quite a test error, but it can impact | ||
// next executions of LogContains, so treat it as an error | ||
t.Errorf("could not close log file: %s", err) | ||
} | ||
}() | ||
|
||
r := bufio.NewReader(logFile) | ||
for { | ||
line, err := r.ReadString('\n') | ||
if err != nil { | ||
if err != io.EOF { | ||
t.Fatalf("error reading log file '%s': %s", logFile.Name(), err) | ||
} | ||
break | ||
} | ||
if strings.Contains(line, s) { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
// openLogFile opens the log file for reading and returns it. | ||
// It also registers a cleanup function to close the file | ||
// when the test ends. | ||
func (b *BeatProc) openLogFile() *os.File { | ||
t := b.t | ||
AndersonQ marked this conversation as resolved.
Show resolved
Hide resolved
|
||
glob := fmt.Sprintf("%s-*.ndjson", filepath.Join(b.tempDir, "filebeat")) | ||
files, err := filepath.Glob(glob) | ||
if err != nil { | ||
t.Fatalf("could not expand log file glob: %s", err) | ||
} | ||
|
||
require.Eventually(t, func() bool { | ||
files, err = filepath.Glob(glob) | ||
if err != nil { | ||
t.Fatalf("could not expand log file glob: %s", err) | ||
} | ||
return len(files) == 1 | ||
}, 5*time.Second, 100*time.Millisecond, | ||
"waiting for log file matching glob '%s' to be created", glob) | ||
|
||
// On a normal operation there must be a single log, if there are more | ||
// than one, then there is an issue and the Beat is logging too much, | ||
// which is enough to stop the test | ||
if len(files) != 1 { | ||
t.Fatalf("there must be only one log file for %s, found: %d", | ||
glob, len(files)) | ||
} | ||
|
||
f, err := os.Open(files[0]) | ||
if err != nil { | ||
t.Fatalf("could not open log file '%s': %s", files[0], err) | ||
} | ||
|
||
return f | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was it just for debugging or we still need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this test ever fails on CI that will be needed. I believe we should keep it there. Nobody investigating a test failure will remember to re-enable that, run it again then disable it.
I'm trying to make it as easy as possible to find and fix anything that could make this test fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the tests output the junit test report that CI uses to generate the test report? The unit tests do this, there probably isn't a reason the integration tests here couldn't either.
This is all controlled through the mage Go Test wrapper so if you are using that you are set.
https://github.com/belimawr/beats/blob/d36f48672653082fd5a8e27795726fb87c733be2/dev-tools/mage/gotest.go#L211
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get how it could help. What I am trying to do here is to make the logs from the Filebeat test binary available to download on CI, so if the test fails we can see why Filebeat failed/did not behave as expected.