diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4be68fd297d..a856cef9557 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -267,7 +267,7 @@ jobs: run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: - runs-on: ubuntu-22.04 # TODO: ubuntu-24.04 + runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - uses: actions/checkout@v4.1.7 diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 397aa0c1ad6..af3df0b5512 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -209,7 +209,12 @@ func TestLogsWithForegroundContainers(t *testing.T) { } func TestTailFollowRotateLogs(t *testing.T) { - t.Parallel() + // FIXME this is flaky by nature... 5 lines is arbitrary, 2000 ms is arbitrary, and both are some sort of educated + // guess that things will mostly always kinda work maybe... + // Furthermore, parallelizing will put pressure on the daemon which might be even slower in answering, increasing + // the risk of transient failure. + // This test needs to be rethought entirely + // t.Parallel() if runtime.GOOS == "windows" { t.Skip("tail log is not supported on Windows") } @@ -217,7 +222,7 @@ func TestTailFollowRotateLogs(t *testing.T) { containerName := testutil.Identifier(t) const sampleJSONLog = `{"log":"A\n","stream":"stdout","time":"2024-04-11T12:01:09.800288974Z"}` - const linesPerFile = 100 + const linesPerFile = 5 defer base.Cmd("rm", "-f", containerName).Run() base.Cmd("run", "-d", "--log-driver", "json-file", @@ -227,10 +232,13 @@ func TestTailFollowRotateLogs(t *testing.T) { "sh", "-euc", "while true; do echo A; done").AssertOK() tailLogCmd := base.Cmd("logs", "-f", containerName) - tailLogCmd.Timeout = 100 * time.Millisecond - tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Combined()), "\n") + tailLogCmd.Timeout = 2000 * time.Millisecond + tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Stdout()), "\n") for _, line := range tailLogs { - assert.Equal(t, "A", line) + if line != "" { + assert.Equal(t, "A", line) + } } + assert.Equal(t, true, len(tailLogs) > linesPerFile) } diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 8174336b8a3..106060bf365 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -296,14 +296,12 @@ func TestRunCgroupParent(t *testing.T) { t.Parallel() base := testutil.NewBase(t) info := base.Info() - containerName := testutil.Identifier(t) - defer base.Cmd("rm", "-f", containerName).Run() - switch info.CgroupDriver { case "none", "": t.Skip("test requires cgroup driver") } + containerName := testutil.Identifier(t) t.Logf("Using %q cgroup driver", info.CgroupDriver) parent := "/foobarbaz" @@ -314,6 +312,13 @@ func TestRunCgroupParent(t *testing.T) { parent = "foobarbaz.slice" } + tearDown := func() { + base.Cmd("rm", "-f", containerName).Run() + } + + tearDown() + t.Cleanup(tearDown) + // cgroup2 without host cgroup ns will just output 0::/ which doesn't help much to verify // we got our expected path. This approach should work for both cgroup1 and 2, there will // just be many more entries for cgroup1 as there'll be an entry per controller. @@ -333,6 +338,9 @@ func TestRunCgroupParent(t *testing.T) { expected := filepath.Join(parent, id) if info.CgroupDriver == "systemd" { expected = filepath.Join(parent, fmt.Sprintf("nerdctl-%s", id)) + if base.Target == testutil.Docker { + expected = filepath.Join(parent, fmt.Sprintf("docker-%s", id)) + } } base.Cmd("exec", containerName, "cat", "/proc/self/cgroup").AssertOutContains(expected) } diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 6383eb3b768..3a4cf4c907b 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -28,6 +28,7 @@ import ( "strings" "time" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" @@ -129,7 +130,15 @@ func (jsonLogger *JSONLogger) PostProcess() error { func viewLogsJSONFile(lvopts LogViewOptions, stdout, stderr io.Writer, stopChannel chan os.Signal) error { logFilePath := jsonfile.Path(lvopts.DatastoreRootPath, lvopts.Namespace, lvopts.ContainerID) if _, err := os.Stat(logFilePath); err != nil { - return fmt.Errorf("failed to stat JSON log file ") + // FIXME: this is a workaround for the actual issue, not a real solution + if errors.Is(err, errdefs.ErrNotFound) { + log.L.Warnf("Racing log file creation. Pausing briefly.") + time.Sleep(200 * time.Millisecond) + _, err = os.Stat(logFilePath) + } + if err != nil { + return fmt.Errorf("failed to stat JSON log file %w", err) + } } if checkExecutableAvailableInPath("tail") {