Skip to content

Commit 527d275

Browse files
committed
pkg/config: add config file search order test
Until now there didn't seem to exists a proper that that actually verifies the containers.conf loading order so fix that. The test got a bit complicated but I coud not find something better. Signed-off-by: Paul Holzinger <[email protected]>
1 parent f0ed5ca commit 527d275

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

pkg/config/search_order_test.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package config
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
. "github.com/onsi/ginkgo/v2"
9+
"github.com/onsi/gomega"
10+
)
11+
12+
var _ = Describe("search order", func() {
13+
It("config file parsing order", func() {
14+
// High level idea, we define 12 file lookup paths. Then we simulate parsing
15+
// of that file tree for all three cases, uid 0 (root), uid 1000 (reads rootless
16+
// specific config files) and uid 500 (also reads rootless config files but not
17+
// the uid 1000 specific one)
18+
//
19+
// To know that each file is getting parsed we use 12 config values and 12 files,
20+
// each file in the order is populated with one less config value.
21+
// So the first value only exits in the /usr/ file and then the next file writes
22+
// one less config value but instead increments the values by one so we can
23+
// differentiate what value is in what file.
24+
25+
configPaths := []string{
26+
"/usr/share/containers/containers.conf",
27+
"/etc/containers/containers.conf",
28+
"/etc/containers/containers.conf.d/1.conf",
29+
"/etc/containers/containers.conf.d/2.conf",
30+
"/etc/containers/containers.rootless.conf",
31+
"/etc/containers/containers.rootless.conf.d/3.conf",
32+
"/etc/containers/containers.rootless.conf.d/4.conf",
33+
"/etc/containers/containers.rootless.conf.d/1000/5.conf",
34+
"/etc/containers/containers.rootless.conf.d/1000/6.conf",
35+
"/home/.config/containers/containers.conf",
36+
"/home/.config/containers/containers.conf.d/7.conf",
37+
"/home/.config/containers/containers.conf.d/8.conf",
38+
}
39+
40+
configFileValues := []string{
41+
`apparmor_profile = "apparmor%d"`,
42+
`base_hosts_file = "base%d"`,
43+
`cgroupns = "cgroupns%d"`,
44+
`cgroups = "cgroups%d"`,
45+
`host_containers_internal_ip = "host%d"`,
46+
`init_path = "init%d"`,
47+
`ipcns = "ipcns%d"`,
48+
`log_driver = "logdriver%d"`,
49+
`log_tag = "logtag%d"`,
50+
`netns = "netns%d"`,
51+
`pidns = "pidns%d"`,
52+
`seccomp_profile = "seccomp%d"`,
53+
}
54+
55+
test := func(config *Config, uid int, testname string) {
56+
gomega.Expect(config.Containers.ApparmorProfile).To(gomega.Equal("apparmor1"), testname)
57+
gomega.Expect(config.Containers.BaseHostsFile).To(gomega.Equal("base2"), testname)
58+
gomega.Expect(config.Containers.CgroupNS).To(gomega.Equal("cgroupns3"), testname)
59+
gomega.Expect(config.Containers.Cgroups).To(gomega.Equal("cgroups4"), testname)
60+
61+
// This is a bit confusing but I did not find a way to make it better readable.
62+
// Basically we have three cases here:
63+
// - uid 0 (root): should not read containers.rootless.conf, values must stay at 4
64+
// - uid != 1000: should read containers.rootless.conf but not
65+
// containers.rootless.conf.d/1000/*.conf, values for the 1000 files must be 7
66+
// - uid == 1000: all files are read so each value should be incremented by 1
67+
hostIP := "host5"
68+
initPath := "init6"
69+
ipcns := "ipcns7"
70+
logDriver := "logdriver7"
71+
logTag := "logtag7"
72+
switch uid {
73+
case 0:
74+
hostIP = "host4"
75+
initPath = "init4"
76+
ipcns = "ipcns4"
77+
logDriver = "logdriver4"
78+
logTag = "logtag4"
79+
case 1000:
80+
logDriver = "logdriver8"
81+
logTag = "logtag9"
82+
}
83+
gomega.Expect(config.Containers.HostContainersInternalIP).To(gomega.Equal(hostIP), testname)
84+
gomega.Expect(config.Containers.InitPath).To(gomega.Equal(initPath), testname)
85+
gomega.Expect(config.Containers.IPCNS).To(gomega.Equal(ipcns), testname)
86+
gomega.Expect(config.Containers.LogDriver).To(gomega.Equal(logDriver), testname)
87+
gomega.Expect(config.Containers.LogTag).To(gomega.Equal(logTag), testname)
88+
89+
gomega.Expect(config.Containers.NetNS).To(gomega.Equal("netns10"), testname)
90+
gomega.Expect(config.Containers.PidNS).To(gomega.Equal("pidns11"), testname)
91+
gomega.Expect(config.Containers.SeccompProfile).To(gomega.Equal("seccomp12"), testname)
92+
}
93+
94+
// sanity check
95+
gomega.Expect(configFileValues).To(gomega.HaveLen(len(configPaths)))
96+
97+
tmpdir := GinkgoT().TempDir()
98+
for i, path := range configPaths {
99+
path := filepath.Join(tmpdir, path)
100+
err := os.MkdirAll(filepath.Dir(path), 0o755)
101+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
102+
103+
f, err := os.Create(path)
104+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
105+
_, err = f.WriteString("[containers]\n")
106+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
107+
for _, val := range configFileValues[i:] {
108+
_, err = fmt.Fprintf(f, val+"\n", i+1)
109+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
110+
}
111+
f.Close()
112+
}
113+
114+
paths := &paths{
115+
usr: filepath.Join(tmpdir, "/usr/share/containers/containers.conf"),
116+
etc: filepath.Join(tmpdir, "/etc/containers/containers.conf"),
117+
home: filepath.Join(tmpdir, "/home/.config/containers/containers.conf"),
118+
uid: 1000,
119+
}
120+
121+
config, err := newLocked(&Options{}, paths)
122+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
123+
test(config, 1000, "lookup with uid 1000")
124+
125+
paths.uid = 500
126+
config, err = newLocked(&Options{}, paths)
127+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
128+
test(config, 500, "lookup with uid 500")
129+
130+
paths.uid = 0
131+
config, err = newLocked(&Options{}, paths)
132+
gomega.Expect(err).ToNot(gomega.HaveOccurred())
133+
test(config, 0, "lookup with uid 0 (root)")
134+
})
135+
})

0 commit comments

Comments
 (0)