diff --git a/run/run_test.go b/run/run_test.go
index 9634c20..b3a34e1 100644
--- a/run/run_test.go
+++ b/run/run_test.go
@@ -28,6 +28,19 @@ func TestRun(t *testing.T) {
t.Fatalf("failed to initialize a testing option: %v", err)
}
+ var journalctlOpt *option.Option
+ var jerr error
+
+ if *subject == "finch" {
+ journalctlOpt, jerr = option.New(
+ []string{"/Applications/Finch/lima/bin/limactl", "shell", "finch", "sudo", "journalctl"},
+ option.Env([]string{"LIMA_HOME=/Applications/Finch/lima/data"}),
+ )
+ }
+ if jerr != nil {
+ t.Fatalf("failed to initialize the journactl option: %v", err)
+ }
+
ginkgo.SynchronizedBeforeSuite(func() []byte {
tests.SetupLocalRegistry(o)
return nil
@@ -44,7 +57,7 @@ func TestRun(t *testing.T) {
tests.Pull(o)
tests.Rm(o)
tests.Rmi(o)
- tests.Run(&tests.RunOption{BaseOpt: o, CGMode: tests.Unified})
+ tests.Run(&tests.RunOption{BaseOpt: o, CGMode: tests.Unified, JournalctlOpt: journalctlOpt})
tests.Start(o)
tests.Stop(o)
tests.Cp(o)
diff --git a/tests/run.go b/tests/run.go
index 1237d24..0373d65 100644
--- a/tests/run.go
+++ b/tests/run.go
@@ -27,6 +27,8 @@ type RunOption struct {
BaseOpt *option.Option
// CGMode is the cgroup mode that the host uses.
CGMode CGMode
+ // JournalctlOpt instructs how to run the journalctl binary. If it's nil, test cases related to `--log-driver journald` will be skipped.
+ JournalctlOpt *option.Option
}
// Run tests running a container image.
@@ -560,6 +562,127 @@ func Run(o *RunOption) {
}
})
}
+ ginkgo.When("running a container with logging flags", func() {
+ ginkgo.It("should set the logging driver as json-file with --log-driver json-file", func() {
+ ctrID := command.StdoutStr(o.BaseOpt, "run", "-d", "--log-driver", "json-file", "--name", testContainerName, defaultImage)
+ logPath := command.StdoutStr(o.BaseOpt, "inspect", testContainerName, "--format", "{{.LogPath}}")
+ gomega.Expect(logPath).Should(gomega.ContainSubstring(fmt.Sprintf("%s-json.log", ctrID)))
+ })
+
+ ginkgo.It("should set the logging path of the logging driver json-file with --log-opt log-path option", func() {
+ tmpDir := ffs.CreateTempDir("finch-test-logging")
+ ginkgo.DeferCleanup(os.RemoveAll, tmpDir)
+ customPath := filepath.Join(tmpDir, testContainerName, testContainerName+"-json.log")
+ command.Run(o.BaseOpt, "run", "-d", "--log-driver", "json-file", "--log-opt", fmt.Sprintf("log-path=%s", customPath),
+ "--name", testContainerName, defaultImage, "echo", "foo")
+ time.Sleep(3 * time.Second)
+ logData, err := os.ReadFile(filepath.Clean(customPath))
+ gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
+ gomega.Expect(string(logData)).To(gomega.ContainSubstring("foo"))
+ })
+
+ ginkgo.It("should set the log max size of the logging driver json-file with --log-opt max-size option", func() {
+ tmpDir := ffs.CreateTempDir("finch-test-logging")
+ ginkgo.DeferCleanup(os.RemoveAll, tmpDir)
+ customPath := filepath.Join(tmpDir, testContainerName, testContainerName+"-json.log")
+ command.Run(o.BaseOpt, "run", "-d", "--log-driver", "json-file", "--log-opt", fmt.Sprintf("log-path=%s", customPath),
+ "--log-opt", "max-size=5k", "--name", testContainerName, defaultImage, "sh", "-c",
+ "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 100 | head -n 1000")
+ time.Sleep(3 * time.Second)
+ logs, err := filepath.Glob(customPath + "*")
+ gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
+ for _, l := range logs {
+ li, err := os.Stat(l)
+ gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
+ // The log file size is compared to 5200 bytes (instead 5k) to keep docker compatibility.
+ //nolint: lll // Ref. https://github.com/containerd/nerdctl/blob/b71443b2a3abc6288944c72229a2e21a1ae7ec6e/cmd/nerdctl/run_test.go#L242-L244
+ gomega.Expect(li.Size()).Should(gomega.BeNumerically("<=", 5200))
+ }
+ })
+
+ ginkgo.It("should set the max number of log files of the logging driver json-file with --log-opt max-file option", func() {
+ tmpDir := ffs.CreateTempDir("finch-test-logging")
+ ginkgo.DeferCleanup(os.RemoveAll, tmpDir)
+ customPath := filepath.Join(tmpDir, testContainerName, testContainerName+"-json.log")
+ command.Run(o.BaseOpt, "run", "-d", "--log-driver", "json-file", "--log-opt", fmt.Sprintf("log-path=%s", customPath),
+ "--log-opt", "max-file=2", "--log-opt", "max-size=2k", "--name", testContainerName, defaultImage, "sh", "-c",
+ "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 100 | head -n 1000")
+ time.Sleep(3 * time.Second)
+ logs, err := filepath.Glob(filepath.Join(filepath.Dir(customPath), testContainerName+"*"))
+ gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
+ gomega.Expect(len(logs)).To(gomega.Equal(2))
+ })
+
+ ginkgo.It("should set the logging driver as journald with --log-driver journald", func() {
+ if o.JournalctlOpt == nil {
+ ginkgo.Skip("Skip the test spec because the journald option is nil.")
+ }
+ ctrID := command.StdoutStr(o.BaseOpt, "run", "-d", "--log-driver", "journald", "--name",
+ testContainerName, defaultImage, "sh", "-c", "echo test")
+ time.Sleep(3 * time.Second)
+ output := command.StdoutStr(o.JournalctlOpt, "--since", "1 minute ago", fmt.Sprintf("SYSLOG_IDENTIFIER=%s", ctrID[:12]))
+ gomega.Expect(output).Should(gomega.ContainSubstring("test"))
+ })
+
+ // TODO: figure out why custom logging tags doesn't work https://docs.docker.com/config/containers/logging/log_tags/
+ ginkgo.It("should set the tag option of the logging driver journald with --log-driver=journald --log-opt=tag={{.FullID}}}", func() {
+ if o.JournalctlOpt == nil {
+ ginkgo.Skip("Skip the test spec because the journald option is nil.")
+ }
+ ctrID := command.StdoutStr(o.BaseOpt, "run", "-d", "--log-driver", "journald", "--name", testContainerName,
+ "--log-opt", "tag={{.FullID}}", defaultImage, "sh", "-c", "echo foo")
+ time.Sleep(3 * time.Second)
+ output := command.StdoutStr(o.JournalctlOpt, "--since", "3 minute ago", fmt.Sprintf("SYSLOG_IDENTIFIER=%s", ctrID))
+ gomega.Expect(output).Should(gomega.ContainSubstring("foo"))
+ })
+
+ ginkgo.It("should set the logging driver as fluentd with --log-driver fluentd", func() {
+ testConfStr := `
+ @type forward
+
+
+
+ @type file
+ path /tmp/log
+ `
+ testConfFilename := "test.conf"
+ testConfFile := ffs.CreateTempFile(testConfFilename, testConfStr)
+ ginkgo.DeferCleanup(os.RemoveAll, testConfFile)
+ fluentCtrID := command.StdoutStr(o.BaseOpt, "run", "-d", "-p", "24224:24224", "-v",
+ fmt.Sprintf("%s:/fluentd/etc/%s", testConfFile, testConfFilename),
+ "-u", "root", "-e", fmt.Sprintf("FLUENTD_CONF=%s", testConfFilename), fluentdImage)
+ time.Sleep(3 * time.Second)
+ ctrID := command.StdoutStr(o.BaseOpt, "run", "-d", "--log-driver", "fluentd", defaultImage, "sh", "-c", "echo foo")
+ output := command.StdoutStr(o.BaseOpt, "exec", fluentCtrID, "sh", "-c", "cat /tmp/log/*.log")
+ gomega.Expect(output).Should(gomega.ContainSubstring("foo"))
+ gomega.Expect(output).Should(gomega.ContainSubstring(ctrID))
+ })
+
+ ginkgo.It("should set the fluentd address with --log-driver fluentd --fluentd-address=127.0.0.1:24225", func() {
+ testConfStr := `
+ @type forward
+
+
+
+ @type file
+ path /tmp/log
+ `
+ testConfFilename := "test.conf"
+ testConfFile := ffs.CreateTempFile(testConfFilename, testConfStr)
+ ginkgo.DeferCleanup(os.RemoveAll, testConfFile)
+ fluentCtrID := command.StdoutStr(o.BaseOpt, "run", "-d", "-p", "24225:24224", "-v",
+ fmt.Sprintf("%s:/fluentd/etc/%s", testConfFile, testConfFilename),
+ "-u", "root", "-e", fmt.Sprintf("FLUENTD_CONF=%s", testConfFilename), fluentdImage)
+ time.Sleep(3 * time.Second)
+ ctrID := command.StdoutStr(o.BaseOpt, "run", "-d", "--log-driver", "fluentd", "--log-opt",
+ "fluentd-address=127.0.0.1:24225", defaultImage, "sh", "-c", "echo foo")
+ output := command.StdoutStr(o.BaseOpt, "exec", fluentCtrID, "sh", "-c", "cat /tmp/log/*.log")
+ gomega.Expect(output).Should(gomega.ContainSubstring("foo"))
+ gomega.Expect(output).Should(gomega.ContainSubstring(ctrID))
+ })
+
+ // TODO: test syslog
+ })
})
}
diff --git a/tests/tests.go b/tests/tests.go
index c63ba9f..4159487 100644
--- a/tests/tests.go
+++ b/tests/tests.go
@@ -27,6 +27,7 @@ import (
const (
alpineImage = "public.ecr.aws/docker/library/alpine:latest"
olderAlpineImage = "public.ecr.aws/docker/library/alpine:3.13"
+ fluentdImage = "public.ecr.aws/docker/library/fluentd:latest"
testImageName = "test:tag"
nonexistentImageName = "ne-repo:ne-tag"
nonexistentContainerName = "ne-ctr"