Fix daemon proxy test for "reload sanitized"

I noticed this was always being skipped because of race conditions
checking the logs.

This change adds a log scanner which will look through the logs line by
line rather than allocating a big buffer.
Additionally it adds a `poll.Check` which we can use to actually wait
for the desired log entry.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Brian Goff 2023-07-28 21:21:17 +00:00 committed by Sebastiaan van Stijn
parent 8197752d68
commit 476e788090
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
2 changed files with 50 additions and 15 deletions

View file

@ -22,6 +22,7 @@ import (
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd"
"gotest.tools/v3/poll"
"gotest.tools/v3/skip"
)
@ -319,32 +320,26 @@ func TestDaemonProxy(t *testing.T) {
// Make sure values are sanitized when reloading the daemon-config
t.Run("reload sanitized", func(t *testing.T) {
t.Parallel()
ctx := context.Background()
const (
proxyRawURL = "https://" + userPass + "example.org"
proxyURL = "https://xxxxx:xxxxx@example.org"
)
d := daemon.New(t)
d.Start(t, "--http-proxy", proxyRawURL, "--https-proxy", proxyRawURL, "--no-proxy", "example.com")
d.Start(t, "--iptables=false", "--http-proxy", proxyRawURL, "--https-proxy", proxyRawURL, "--no-proxy", "example.com")
defer d.Stop(t)
err := d.Signal(syscall.SIGHUP)
assert.NilError(t, err)
logs, err := d.ReadLogFile()
poll.WaitOn(t, d.PollCheckLogs(ctx, "Reloaded configuration:"))
poll.WaitOn(t, d.PollCheckLogs(ctx, proxyURL))
ok, logs, err := d.ScanLogs(ctx, userPass)
assert.NilError(t, err)
// FIXME: there appears to ba a race condition, which causes ReadLogFile
// to not contain the full logs after signaling the daemon to reload,
// causing the test to fail here. As a workaround, check if we
// received the "reloaded" message after signaling, and only then
// check that it's sanitized properly. For more details on this
// issue, see https://github.com/moby/moby/pull/42835/files#r713120315
if !strings.Contains(string(logs), "Reloaded configuration:") {
t.Skip("Skipping test, because we did not find 'Reloaded configuration' in the logs")
}
assert.Assert(t, is.Contains(string(logs), proxyURL))
assert.Assert(t, !strings.Contains(string(logs), userPass), "logs should not contain the non-sanitized proxy URL: %s", string(logs))
assert.Assert(t, !ok, "logs should not contain the non-sanitized proxy URL: %s", logs)
})
}

View file

@ -1,8 +1,10 @@
package daemon // import "github.com/docker/docker/testutil/daemon"
import (
"bufio"
"context"
"encoding/json"
"io"
"net/http"
"os"
"os/exec"
@ -25,6 +27,7 @@ import (
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
"gotest.tools/v3/assert"
"gotest.tools/v3/poll"
)
// LogT is the subset of the testing.TB interface used by the daemon.
@ -310,6 +313,43 @@ func (d *Daemon) TailLogsT(t LogT, n int) {
}
}
// PollCheckLogs is a poll.Check that checks the daemon logs for the passed in string (`contains`).
func (d *Daemon) PollCheckLogs(ctx context.Context, contains string) poll.Check {
return func(t poll.LogT) poll.Result {
ok, _, err := d.ScanLogs(ctx, contains)
if err != nil {
return poll.Error(err)
}
if !ok {
return poll.Continue("waiting for %q in daemon logs", contains)
}
return poll.Success()
}
}
// ScanLogs scans the daemon logs for the passed in string (`contains`).
// If the context is canceled, the function returns false but does not error out the test.
func (d *Daemon) ScanLogs(ctx context.Context, contains string) (bool, string, error) {
stat, err := d.logFile.Stat()
if err != nil {
return false, "", err
}
rdr := io.NewSectionReader(d.logFile, 0, stat.Size())
scanner := bufio.NewScanner(rdr)
for scanner.Scan() {
if strings.Contains(scanner.Text(), contains) {
return true, scanner.Text(), nil
}
select {
case <-ctx.Done():
return false, "", ctx.Err()
default:
}
}
return false, "", scanner.Err()
}
// TailLogs tails N lines from the daemon logs
func (d *Daemon) TailLogs(n int) ([][]byte, error) {
logF, err := os.Open(d.logFile.Name())