Skip to content

Commit f65db50

Browse files
Merge pull request #26765 from 2004joshua/log_location
feat: added log_path support for configuration files
2 parents a97d90c + 930cd25 commit f65db50

File tree

30 files changed

+784
-78
lines changed

30 files changed

+784
-78
lines changed

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/checkpoint-restore/go-criu/v7 v7.2.0
1313
github.com/containernetworking/plugins v1.7.1
1414
github.com/containers/buildah v1.41.0
15-
github.com/containers/common v0.64.0
15+
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b
1616
github.com/containers/conmon v2.0.20+incompatible
1717
github.com/containers/gvisor-tap-vsock v0.8.6
1818
github.com/containers/image/v5 v5.36.1
@@ -63,7 +63,7 @@ require (
6363
github.com/shirou/gopsutil/v4 v4.25.7
6464
github.com/sirupsen/logrus v1.9.3
6565
github.com/spf13/cobra v1.9.1
66-
github.com/spf13/pflag v1.0.6
66+
github.com/spf13/pflag v1.0.7
6767
github.com/stretchr/testify v1.10.0
6868
github.com/vbauerster/mpb/v8 v8.10.2
6969
github.com/vishvananda/netlink v1.3.1
@@ -154,7 +154,7 @@ require (
154154
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
155155
github.com/proglottis/gpgme v0.1.4 // indirect
156156
github.com/rivo/uniseg v0.4.7 // indirect
157-
github.com/seccomp/libseccomp-golang v0.11.0 // indirect
157+
github.com/seccomp/libseccomp-golang v0.11.1 // indirect
158158
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
159159
github.com/segmentio/ksuid v1.0.4 // indirect
160160
github.com/sigstore/fulcio v1.6.6 // indirect

go.sum

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/
6464
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
6565
github.com/containers/buildah v1.41.0 h1:GU350UeX6BkZrgCE3SB/d1Hu4xBaHUX07ayiJTvJD54=
6666
github.com/containers/buildah v1.41.0/go.mod h1:1Ds26B4E4Z3NeLdi3xjjk8S72KVv2/xiFYYpwfFDgXI=
67-
github.com/containers/common v0.64.0 h1:Jdjq1e5tqrLov9tcAVc/AfvQCgX4krhcfDBgOXwrSfw=
68-
github.com/containers/common v0.64.0/go.mod h1:bq2UIiFP8vUJdgM+WN8E8jkD7wF69SpDRGzU7epJljg=
67+
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b h1:k6Ir7PSGAqDzJyUHREJQYbJG+TN43anXoGcNX2gmLkA=
68+
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b/go.mod h1:XVM+3mWPo2J4KSrGkRFKGDTgd3FwknWaDq+uQ4Dhb6E=
6969
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
7070
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
7171
github.com/containers/gvisor-tap-vsock v0.8.6 h1:9SeAXK+K2o36CtrgYk6zRXbU3zrayjvkrI8b7/O6u5A=
@@ -377,8 +377,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEV
377377
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
378378
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
379379
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
380-
github.com/seccomp/libseccomp-golang v0.11.0 h1:SDkcBRqGLP+sezmMACkxO1EfgbghxIxnRKfd6mHUEis=
381-
github.com/seccomp/libseccomp-golang v0.11.0/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
380+
github.com/seccomp/libseccomp-golang v0.11.1 h1:wuk4ZjSx6kyQII4rj6G6fvVzRHQaSiPvccJazDagu4g=
381+
github.com/seccomp/libseccomp-golang v0.11.1/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
382382
github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc=
383383
github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw=
384384
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
@@ -403,8 +403,9 @@ github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU
403403
github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
404404
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
405405
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
406-
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
407406
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
407+
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
408+
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
408409
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=
409410
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=
410411
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

libpod/options.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"errors"
77
"fmt"
88
"net"
9+
"os"
10+
"path/filepath"
911
"strings"
1012
"syscall"
1113
"time"
@@ -1041,8 +1043,16 @@ func WithLogPath(path string) CtrCreateOption {
10411043
if path == "" {
10421044
return fmt.Errorf("log path must be set: %w", define.ErrInvalidArg)
10431045
}
1046+
if isDirectory(path) {
1047+
containerDir := filepath.Join(path, ctr.ID())
1048+
if err := os.Mkdir(containerDir, 0755); err != nil {
1049+
return fmt.Errorf("failed to create container log directory %s: %w", containerDir, err)
1050+
}
10441051

1045-
ctr.config.LogPath = path
1052+
ctr.config.LogPath = filepath.Join(containerDir, "ctr.log")
1053+
} else {
1054+
ctr.config.LogPath = path
1055+
}
10461056

10471057
return nil
10481058
}

libpod/util.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,11 @@ func evalSymlinksIfExists(toCheck string) (string, error) {
285285
}
286286
return checkedVal, nil
287287
}
288+
289+
func isDirectory(path string) bool {
290+
info, err := os.Stat(path)
291+
if err != nil {
292+
return false
293+
}
294+
return info.IsDir()
295+
}

pkg/specgen/generate/kube/kube.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
228228

229229
s.ImageVolumes = opts.ImageVolumes
230230

231+
if rtc.Containers.LogPath != "" {
232+
s.LogConfiguration.Path = rtc.Containers.LogPath
233+
}
234+
231235
s.LogConfiguration.Options = make(map[string]string)
232236
for _, o := range opts.LogOptions {
233237
opt, val, hasVal := strings.Cut(o, "=")

pkg/specgenutil/specgen.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
844844
return err
845845
}
846846

847+
if rtc.Containers.LogPath != "" {
848+
s.LogConfiguration.Path = rtc.Containers.LogPath
849+
}
850+
847851
logOpts := make(map[string]string)
848852
for _, o := range c.LogOptions {
849853
key, val, hasVal := strings.Cut(o, "=")
@@ -865,6 +869,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
865869
logOpts[key] = val
866870
}
867871
}
872+
868873
if len(s.LogConfiguration.Options) == 0 || len(c.LogOptions) != 0 {
869874
s.LogConfiguration.Options = logOpts
870875
}

test/e2e/play_kube_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6310,4 +6310,85 @@ spec:
63106310
session.WaitWithDefaultTimeout()
63116311
Expect(session).Should(ExitWithError(125, "invalid signal: noSuchSignal"))
63126312
})
6313+
6314+
It("test with custom log path from containers.conf", func() {
6315+
customLogPath := filepath.Join(podmanTest.TempDir, "custom-logs")
6316+
expectedMessage := "Pod started, checking logs from test"
6317+
6318+
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
6319+
configContent := fmt.Sprintf(`[containers]
6320+
log_driver = "k8s-file"
6321+
log_path = "%s"
6322+
`, customLogPath)
6323+
6324+
err := os.WriteFile(conffile, []byte(configContent), 0644)
6325+
Expect(err).ToNot(HaveOccurred())
6326+
6327+
err = os.MkdirAll(customLogPath, 0755)
6328+
Expect(err).ToNot(HaveOccurred())
6329+
6330+
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
6331+
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
6332+
6333+
if IsRemote() {
6334+
podmanTest.RestartRemoteService()
6335+
}
6336+
6337+
kubeYaml := filepath.Join(podmanTest.TempDir, "test-pod.yaml")
6338+
podYamlContent := fmt.Sprintf(`apiVersion: v1
6339+
kind: Pod
6340+
metadata:
6341+
name: log-test-pod
6342+
spec:
6343+
restartPolicy: Never
6344+
containers:
6345+
- name: logger-container
6346+
image: %s
6347+
command: ["/bin/sh", "-c", "echo '%s'; sleep 2"]
6348+
`, CITEST_IMAGE, expectedMessage)
6349+
6350+
err = os.WriteFile(kubeYaml, []byte(podYamlContent), 0644)
6351+
Expect(err).ToNot(HaveOccurred())
6352+
6353+
podmanTest.PodmanExitCleanly("kube", "play", kubeYaml)
6354+
6355+
podmanTest.PodmanExitCleanly("wait", "log-test-pod-logger-container")
6356+
6357+
customLogDirs, err := os.ReadDir(customLogPath)
6358+
Expect(err).ToNot(HaveOccurred())
6359+
Expect(customLogDirs).To(HaveLen(2), "Should have exactly two container log directories (infra + app container)")
6360+
6361+
var appContainerLogDir string
6362+
var logContent string
6363+
found := false
6364+
6365+
for _, dir := range customLogDirs {
6366+
if !dir.IsDir() {
6367+
continue
6368+
}
6369+
containerLogDir := dir.Name()
6370+
logFilePath := filepath.Join(customLogPath, containerLogDir, "ctr.log")
6371+
6372+
if _, err := os.Stat(logFilePath); err != nil {
6373+
continue
6374+
}
6375+
6376+
content, err := os.ReadFile(logFilePath)
6377+
if err != nil {
6378+
continue
6379+
}
6380+
6381+
if strings.Contains(string(content), expectedMessage) {
6382+
appContainerLogDir = containerLogDir
6383+
logContent = string(content)
6384+
found = true
6385+
break
6386+
}
6387+
}
6388+
6389+
Expect(found).To(BeTrue(), "Should find log file with expected message")
6390+
6391+
Expect(appContainerLogDir).ToNot(BeEmpty(), "Should have found application container log directory")
6392+
Expect(logContent).To(ContainSubstring(expectedMessage), "Log file should contain the expected message")
6393+
})
63136394
})

test/e2e/run_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net"
99
"os"
1010
"path/filepath"
11+
"regexp"
1112
"strconv"
1213
"strings"
1314
"syscall"
@@ -2456,4 +2457,84 @@ WORKDIR /madethis`, BB)
24562457
Expect(inspectData[0].Config.Annotations).To(Not(HaveKey(annoName)))
24572458
Expect(inspectData[0].Config.Annotations).To(Not(HaveKey("testlabel")))
24582459
})
2460+
2461+
It("podman run log-opt overrides containers.conf path", func() {
2462+
expectedMessage := "CLI override test message"
2463+
confLogPath := filepath.Join(podmanTest.TempDir, "conf-logs")
2464+
2465+
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
2466+
configContent := fmt.Sprintf(`[containers]
2467+
log_driver = "k8s-file"
2468+
log_path = "%s"
2469+
`, confLogPath)
2470+
2471+
err := os.WriteFile(conffile, []byte(configContent), 0644)
2472+
Expect(err).ToNot(HaveOccurred())
2473+
2474+
err = os.MkdirAll(confLogPath, 0755)
2475+
Expect(err).ToNot(HaveOccurred())
2476+
2477+
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
2478+
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
2479+
2480+
if IsRemote() {
2481+
podmanTest.RestartRemoteService()
2482+
}
2483+
2484+
cliLogPath := filepath.Join(podmanTest.TempDir, "cli-override.log")
2485+
podmanTest.PodmanExitCleanly("run", "--rm", "--log-driver", "k8s-file", "--log-opt", fmt.Sprintf("path=%s", cliLogPath), ALPINE, "echo", expectedMessage)
2486+
2487+
confLogDirs, err := os.ReadDir(confLogPath)
2488+
Expect(err).ToNot(HaveOccurred(), "Should be able to read config log directory that we created")
2489+
Expect(confLogDirs).To(BeEmpty(), "Config file log path should not be used when CLI overrides")
2490+
2491+
content, err := os.ReadFile(cliLogPath)
2492+
Expect(err).ToNot(HaveOccurred())
2493+
Expect(string(content)).To(ContainSubstring(expectedMessage))
2494+
Expect(string(content)).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.*stdout F ` + regexp.QuoteMeta(expectedMessage)))
2495+
2496+
_ = os.Remove(cliLogPath)
2497+
})
2498+
2499+
It("podman run uses containers.conf log_path", func() {
2500+
expectedMessage := "Config file path test message"
2501+
confLogPath := filepath.Join(podmanTest.TempDir, "conf-logs")
2502+
2503+
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
2504+
configContent := fmt.Sprintf(`[containers]
2505+
log_driver = "k8s-file"
2506+
log_path = "%s"
2507+
`, confLogPath)
2508+
2509+
err := os.WriteFile(conffile, []byte(configContent), 0644)
2510+
Expect(err).ToNot(HaveOccurred())
2511+
2512+
err = os.MkdirAll(confLogPath, 0755)
2513+
Expect(err).ToNot(HaveOccurred())
2514+
2515+
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
2516+
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
2517+
2518+
if IsRemote() {
2519+
podmanTest.RestartRemoteService()
2520+
}
2521+
2522+
containerName := "test-conf-log-container"
2523+
2524+
podmanTest.PodmanExitCleanly("run", "--name", containerName, ALPINE, "echo", expectedMessage)
2525+
session := podmanTest.PodmanExitCleanly("inspect", "--format", "{{.Id}}", containerName)
2526+
2527+
containerID := strings.TrimSpace(session.OutputToString())
2528+
logFilePath := filepath.Join(confLogPath, containerID, "ctr.log")
2529+
2530+
inspectSession := podmanTest.PodmanExitCleanly("inspect", "--format", "{{.HostConfig.LogConfig.Path}}", containerName)
2531+
inspectedPath := strings.TrimSpace(inspectSession.OutputToString())
2532+
Expect(inspectedPath).To(Equal(logFilePath), "Log path in inspect data should match the path from containers.conf")
2533+
2534+
content, err := os.ReadFile(logFilePath)
2535+
Expect(err).ToNot(HaveOccurred())
2536+
2537+
Expect(string(content)).To(ContainSubstring(expectedMessage), "Log should contain expected message")
2538+
Expect(string(content)).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.*stdout F `+regexp.QuoteMeta(expectedMessage)), "Log should follow k8s-file format")
2539+
})
24592540
})

vendor/github.com/containers/common/pkg/config/config.go

Lines changed: 8 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/containers/common/pkg/config/config_local.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)