Skip to content

Commit 697c412

Browse files
committed
Add support for drop-in config
Signed-off-by: Harshal Patil <[email protected]>
1 parent c051e2a commit 697c412

File tree

6 files changed

+106
-19
lines changed

6 files changed

+106
-19
lines changed

types/options.go

+50-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ var (
4949
defaultConfigFile = SystemConfigFile
5050
// DefaultStoreOptions is a reasonable default set of options.
5151
defaultStoreOptions StoreOptions
52+
53+
// defaultOverrideConfigFile path to override the default system wide storage.conf file
54+
defaultOverrideConfigFile = "/etc/containers/storage.conf"
55+
56+
// defaultDropInConfigDir path to the folder containing drop in config files
57+
defaultDropInConfigDir = "/etc/containers/storage.conf.d"
5258
)
5359

5460
func loadDefaultStoreOptions() {
@@ -114,11 +120,53 @@ func loadDefaultStoreOptions() {
114120

115121
// loadStoreOptions returns the default storage ops for containers
116122
func loadStoreOptions() (StoreOptions, error) {
117-
storageConf, err := DefaultConfigFile()
123+
baseConf, err := DefaultConfigFile()
118124
if err != nil {
119125
return defaultStoreOptions, err
120126
}
121-
return loadStoreOptionsFromConfFile(storageConf)
127+
128+
// Load the base config file
129+
baseOptions, err := loadStoreOptionsFromConfFile(baseConf)
130+
if err != nil {
131+
return defaultStoreOptions, err
132+
}
133+
134+
if _, err := os.Stat(defaultDropInConfigDir); err == nil {
135+
// The directory exists, so merge the configuration from this directory
136+
err = mergeConfigFromDirectory(&baseOptions, defaultDropInConfigDir)
137+
if err != nil {
138+
return defaultStoreOptions, err
139+
}
140+
} else if !os.IsNotExist(err) {
141+
// There was an error other than the directory not existing
142+
return defaultStoreOptions, err
143+
}
144+
145+
return baseOptions, nil
146+
}
147+
148+
func mergeConfigFromDirectory(baseOptions *StoreOptions, configDir string) error {
149+
return filepath.Walk(configDir, func(path string, info os.FileInfo, err error) error {
150+
if err != nil {
151+
return err
152+
}
153+
if info.IsDir() {
154+
return nil
155+
}
156+
157+
// Only consider files with .conf extension
158+
if filepath.Ext(path) != ".conf" {
159+
return nil
160+
}
161+
162+
// Load drop-in options from the current file
163+
err = ReloadConfigurationFile(path, baseOptions)
164+
if err != nil {
165+
return err
166+
}
167+
168+
return nil
169+
})
122170
}
123171

124172
// usePerUserStorage returns whether the user private storage must be used.

types/options_darwin.go

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ const (
88
SystemConfigFile = "/usr/share/containers/storage.conf"
99
)
1010

11-
var defaultOverrideConfigFile = "/etc/containers/storage.conf"
12-
1311
// canUseRootlessOverlay returns true if the overlay driver can be used for rootless containers
1412
func canUseRootlessOverlay(home, runhome string) bool {
1513
return false

types/options_freebsd.go

-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ const (
88
SystemConfigFile = "/usr/local/share/containers/storage.conf"
99
)
1010

11-
// defaultConfigFile path to the system wide storage.conf file
12-
var (
13-
defaultOverrideConfigFile = "/usr/local/etc/containers/storage.conf"
14-
)
15-
1611
// canUseRootlessOverlay returns true if the overlay driver can be used for rootless containers
1712
func canUseRootlessOverlay(home, runhome string) bool {
1813
return false

types/options_linux.go

-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ const (
1616
SystemConfigFile = "/usr/share/containers/storage.conf"
1717
)
1818

19-
// defaultConfigFile path to the system wide storage.conf file
20-
var (
21-
defaultOverrideConfigFile = "/etc/containers/storage.conf"
22-
)
23-
2419
// canUseRootlessOverlay returns true if the overlay driver can be used for rootless containers
2520
func canUseRootlessOverlay(home, runhome string) bool {
2621
// we check first for fuse-overlayfs since it is cheaper.

types/options_test.go

+56
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,59 @@ func TestReloadConfigurationFile(t *testing.T) {
206206

207207
assert.Equal(t, strings.Contains(content.String(), "Failed to decode the keys [\\\"foo\\\" \\\"storage.options.graphroot\\\"] from \\\"./storage_broken.conf\\\"\""), true)
208208
}
209+
210+
func TestMergeConfigFromDirectory(t *testing.T) {
211+
tempDir, err := os.MkdirTemp("", "testConfigDir")
212+
if err != nil {
213+
t.Fatalf("Failed to create temp dir: %v", err)
214+
}
215+
defer os.RemoveAll(tempDir)
216+
217+
// Creating a mix of files with .txt and .conf extensions
218+
fileNames := []string{"config1.conf", "config2.conf", "ignore.txt", "config3.conf", "config4.txt"}
219+
contents := []string{
220+
`[storage]
221+
runroot = 'temp/run1'
222+
graphroot = 'temp/graph1'`,
223+
`[storage]
224+
runroot = 'temp/run2'
225+
graphroot = 'temp/graph2'`,
226+
`[storage]
227+
runroot = 'should/ignore'
228+
graphroot = 'should/ignore'`,
229+
`[storage]
230+
runroot = 'temp/run3'
231+
graphroot = 'temp/graph3'`,
232+
`[storage]
233+
runroot = 'temp/run4'
234+
graphroot = 'temp/graph4'`,
235+
}
236+
for i, fileName := range fileNames {
237+
filePath := filepath.Join(tempDir, fileName)
238+
if err := os.WriteFile(filePath, []byte(contents[i]), 0o666); err != nil {
239+
t.Fatalf("Failed to write to temp file: %v", err)
240+
}
241+
}
242+
243+
// Set base options
244+
baseOptions := StoreOptions{
245+
RunRoot: "initial/run",
246+
GraphRoot: "initial/graph",
247+
}
248+
249+
// Expected results after merging configurations from only .conf files
250+
expectedOptions := StoreOptions{
251+
RunRoot: "temp/run3", // Last .conf file (config3.conf) read overrides earlier values
252+
GraphRoot: "temp/graph3",
253+
}
254+
255+
// Run the merging function
256+
err = mergeConfigFromDirectory(&baseOptions, tempDir)
257+
if err != nil {
258+
t.Fatalf("Error merging config from directory: %v", err)
259+
}
260+
261+
if baseOptions.RunRoot != expectedOptions.RunRoot || baseOptions.GraphRoot != expectedOptions.GraphRoot {
262+
t.Errorf("Expected RunRoot to be %q and GraphRoot to be %q, got RunRoot %q and GraphRoot %q", expectedOptions.RunRoot, expectedOptions.GraphRoot, baseOptions.RunRoot, baseOptions.GraphRoot)
263+
}
264+
}

types/options_windows.go

-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ const (
88
SystemConfigFile = "/usr/share/containers/storage.conf"
99
)
1010

11-
// defaultConfigFile path to the system wide storage.conf file
12-
var (
13-
defaultOverrideConfigFile = "/etc/containers/storage.conf"
14-
)
15-
1611
// canUseRootlessOverlay returns true if the overlay driver can be used for rootless containers
1712
func canUseRootlessOverlay(home, runhome string) bool {
1813
return false

0 commit comments

Comments
 (0)