Skip to content

Commit 6e68510

Browse files
committed
design doc: config file parsing changes
As part of podman 6 we like to improve and consolidate how we parse our various config files. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
1 parent c457e50 commit 6e68510

File tree

1 file changed

+352
-0
lines changed

1 file changed

+352
-0
lines changed
Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
# Change Request
2+
3+
<!--
4+
This template is used to propose and discuss major new features to be added to Podman, Buildah, Skopeo, Netavark, and associated libraries.
5+
The creation of a design document prior to feature implementation is not mandatory, but is encouraged.
6+
Before major features are implemented, a pull request should be opened against the Podman repository with a completed version of this template.
7+
Discussion on the feature will occur in the pull request.
8+
Merging the pull request will constitute approval by project maintainers to proceed with implementation work.
9+
When the feature is completed and merged, this document should be removed to avoid cluttering the repository.
10+
It will remain in the Git history for future retrieval if necessary.
11+
-->
12+
13+
## **Short Summary**
14+
15+
Unify (and rework) our config file parsing logic to make the various config files all behave
16+
the same parsing wise so users can better understand how it works.
17+
18+
## **Objective**
19+
20+
We have several config files such a containers.conf, storage.conf, registries.conf and more that
21+
get all implement their own parsing logic and have a different feature set. The goal is to
22+
consolidate the parsing into a separate package and then port all files to use that package
23+
instead making them behave consistently.
24+
25+
## **Detailed Description:**
26+
27+
### General
28+
29+
Add new package to the storage library (`go.podman.io/storage/pkg/configfile`) which implements
30+
the core logic of how to read config files. The goal of the package is to define with config paths
31+
to use and in what order.
32+
33+
It will however not define the structs and fields used for the actual content in each file, these
34+
stay where there are defined currently and the plan is to have the code there call into the `configfile`
35+
package to read the files in the same way.
36+
37+
#### Search locations:
38+
39+
Linux:
40+
41+
- `/usr/share/containers/<name>.conf`
42+
- `/usr/share/containers/<name>.conf.d/`
43+
- `/usr/share/containers/<name>.rootful.conf.d/` (only when UID == 0)
44+
- `/usr/share/containers/<name>.rootless.conf.d/` (only when UID > 0)
45+
- `/usr/share/containers/<name>.rootless.conf.d/<UID>/` (only when UID > 0)
46+
47+
- `/etc/containers/<name>.conf`
48+
- `/etc/containers/<name>.conf.d/`
49+
- `/etc/containers/<name>.rootful.conf.d/` (only when UID == 0)
50+
- `/etc/containers/<name>.rootless.conf.d/` (only when UID > 0)
51+
- `/etc/containers/<name>.rootless.conf.d/<UID>/` (only when UID > 0)
52+
53+
- `$XDG_CONFIG_HOME/containers/<name>.conf`
54+
- `$XDG_CONFIG_HOME/containers/<name>.conf.d/`
55+
(if $XDG_CONFIG_HOME is empty then it uses $HOME/.config)
56+
This homedir lookup will also be done by root [1].
57+
58+
Where `<name>` is `containers`, `storage` or `registries` for each config file.
59+
60+
The `<name>.rootless.conf.d/<UID>/` is a directory named by the user id. Only the user with this
61+
exact uid match will read the config files in this directory.
62+
The use case is for admin to be able to set a default for a specific user without having to write
63+
into their home directory. Note this is not intended as security mechanism, the user home directory
64+
config files will still have higher priority.
65+
66+
FreeBSD:
67+
68+
Same as Linux except `/usr/share` is `/usr/local/share` and `/etc` is `/usr/local/etc`.
69+
70+
Windows:
71+
72+
There is no `/usr` equivalent, for `/etc` we instead lookup `ProgramData` env and use that one.
73+
And instead of `XDG_CONFIG_HOME` which isn't used on windows we use `APPDATA`.
74+
75+
MacOS:
76+
77+
Same as Linux.
78+
79+
#### Load order
80+
81+
I propose adopting the UAPI config file specification for loading config files (version 1.0):
82+
https://uapi-group.org/specifications/specs/configuration_files_specification/
83+
84+
Based on that the files must be loaded in this order:
85+
86+
Read `$XDG_CONFIG_HOME/containers/<name>.conf`, only if this file doesn't exists read
87+
`/etc/containers/<name>.conf`, and if that doesn't exists read `/usr/share/containers/<name>.conf`
88+
As such setting an empty file on `$XDG_CONFIG_HOME/containers/<name>.conf` would cause us to ignore
89+
all possible options there were set in the other files.
90+
Note: This is different from the current containers.conf loading where we would have read all files.
91+
92+
Regardless of which file has been loaded above it then must read the drop-in locations in the following order:
93+
94+
- `/usr/share/containers/<name>.conf.d/`
95+
- `/usr/share/containers/<name>.rootful.conf.d/` (UID == 0)
96+
- `/usr/share/containers/<name>.rootless.conf.d/` (UID > 0)
97+
- `/usr/share/containers/containers.rootless.conf.d/<UID>/` (UID > 0)
98+
99+
- `/etc/containers/<name>.conf.d/`
100+
- `/etc/containers/<name>.rootful.conf.d/` (UID == 0)
101+
- `/etc/containers/<name>.rootless.conf.d/` (UID > 0)
102+
- `/etc/containers/containers.rootless.conf.d/<UID>/` (UID > 0)
103+
104+
- `$XDG_CONFIG_HOME/containers/<name>.conf.d/`
105+
106+
Only files read with the `.conf` file extension are read.
107+
108+
If there is a drop-in file with the same filename as in a prior location it will replace
109+
the prior one and only the latest match is read. Once we have the list of all drop-in files
110+
they get sorted lexicographic. The later files have a higher priority so they can overwrite
111+
options set in a prior file.
112+
113+
##### Example
114+
115+
Consider the following files:
116+
117+
`/usr/share/containers/containers.conf` (overridden by `/etc/containers/containers.conf`):
118+
```
119+
field_1 = a
120+
```
121+
122+
`/etc/containers/containers.conf`:
123+
```
124+
field_2 = b
125+
```
126+
127+
`/usr/share/containers/containers.conf.d/10-vendor.conf` (overridden by `$XDG_CONFIG_HOME/containers/containers.conf.d/10-vendor.conf`):
128+
```
129+
field_3 = c
130+
```
131+
132+
`/usr/share/containers/containers.conf.d/99-important.conf`:
133+
```
134+
field_4 = d
135+
```
136+
137+
`/usr/share/containers/containers.rootless.conf.d/50-my.conf`:
138+
```
139+
field_5 = e
140+
```
141+
142+
`$XDG_CONFIG_HOME/containers/containers.conf.d/10-vendor.conf`:
143+
```
144+
# empty
145+
```
146+
147+
`$XDG_CONFIG_HOME/containers/containers.conf.d/33-opt.conf` (this is read but field_4 is overridden by `/usr/share/containers/containers.conf.d/99-important.conf` as `99-important.conf` is sorted later):
148+
```
149+
field_4 = user
150+
field_6 = f
151+
```
152+
153+
Now parsing this as user with UID 1000 results in this final config:
154+
155+
```
156+
field_2 = b
157+
field_4 = d
158+
field_5 = e
159+
field_6 = f
160+
```
161+
162+
#### Environment Variables
163+
164+
The following two envs should be defined for each config file:
165+
166+
`CONTAINERS_<name>_CONF`: If set only read the given file in this env and nothing else.
167+
`CONTAINERS_<name>_CONF_OVERRIDE`: If set append the given file as last file after parsing
168+
all other files as normal. Useful to overwrite a single field for testing without overwriting
169+
the rest of the system configuration.
170+
171+
As special case for containers.conf the name of the vars is `CONTAINERS_CONF` and `CONTAINERS_CONF_OVERRIDE`.
172+
173+
The handling of these should be part of the `configfile` package.
174+
175+
#### Appending arrays
176+
177+
The toml parser by default replaces arrays in each file which makes it impossible to append values in drop-ins, etc...
178+
179+
containers.conf already has a work for that with a custom syntax to trigger appending:
180+
```
181+
field = ["val", {append=true}]
182+
```
183+
I propose we adapt the same universally for the other config files.
184+
185+
https://github.com/containers/container-libs/blob/main/common/docs/containers.conf.5.md#appending-to-string-arrays
186+
187+
This means moving the `common/internal/attributedstring` into the new configfile package so all callers can use it.
188+
189+
#### Scope
190+
191+
##### containers.conf
192+
193+
No changes except `/etc/containers/containers.rootless.conf` search location has been removed. It has just been added
194+
in 5.7 so I don't think it would cause major concerns to drop it again.
195+
196+
The reason to not support the main file with rootless/rootful now is that it is not obvious how this should interact
197+
with the parsing, should it replace the main config file or act like a drop in? As such I think it is better to not
198+
support this and we should generally push all users to use a drop instead of editing the main file.
199+
200+
Also there was/is some discussion of splitting containers.conf in two files as currently there are fields in there
201+
that are only read on the server side while others only get used on the client side which makes using it in a remote
202+
context such as podman machine confusing. For now this is not part of this design doc, we may make another design docs
203+
just for this in case we like to move forward on it.
204+
205+
containers.conf also supports "Modules", i.e. `podman --module name.conf ...` which adds additional drop-in files at
206+
the end after the regular config files. This functionality should be preserved but don't expand module support to the
207+
other files.
208+
209+
##### storage.conf
210+
211+
Deprecate `rootless_storage_path` option. With the `rootless/rootful` config location and admin could just use
212+
`graphroot` in the location in the rootless file location. As such there is no need to special case these fields
213+
in the parser.
214+
215+
String arrays in the config will need to get switched to the attributedstring type, as described under Appending arrays.
216+
217+
##### registries.conf
218+
219+
Remove V1 config layout to simplify the parsing logic. If we do major config changes we might as well take the
220+
chance and remove this old format.
221+
Currently the V1 format is already rejected for drop-in files so this just effects the main config file.
222+
223+
Additionally there might be a few challenges here, c/image uses the SystemContext struct which allows
224+
users to set `RootForImplicitAbsolutePaths`, `SystemRegistriesConfPath`, `SystemRegistriesConfDirPath`.
225+
We must continue to support them as they are used by various tools.
226+
For `RootForImplicitAbsolutePaths` we update it to check bot the `/usr` and `/etc` locations.
227+
When `SystemRegistriesConfPath` or `SystemRegistriesConfDirPath` are used don't do the normal parsing
228+
and just read the file/directory specified there and ignore the environment variables.
229+
230+
As described under the Environment Variables section the handling for `CONTAINERS_REGISTRIES_CONF` is moved
231+
out of Podman, and common/libimage into the actual `configfile` package. As such all users of c/image will
232+
be able to use this without having each caller specify their own env.
233+
As part of this I propose removing support for the old `REGISTRIES_CONFIG_PATH` env which was never documented
234+
and replaced by `CONTAINERS_REGISTRIES_CONF` in commit c9ef2607104a0b17e5146b3ee01852edb7d3d688 (over 4 years ago).
235+
Currently there is an issue because Buildah doesn't support it [4].
236+
237+
String arrays in the config will need to get switched to the attributedstring type, as described under Appending arrays.
238+
To avoid breaking public consumers of `V2RegistriesConf` we should use a new type instead and then copy values accordingly.
239+
As part of this deprecate the `V2RegistriesConf` type and avoid expanding it to not expose so much "internal" details.
240+
241+
##### registries.d
242+
243+
Note registries.d is confusingly a completely different config file format from registries.conf.d.
244+
245+
Right now it only uses `$HOME/.config/containers/registries.d` or `/etc/containers/registries.d`
246+
247+
For consistency it would be best if it uses all drop in paths like shown above without the "main"
248+
file as this only support drop-in locations.
249+
250+
Additionally there seems to exit code duplication in `podman/pkg/trust`. We should find a way to
251+
not duplicate this logic at all in podman again.
252+
253+
##### certs.d
254+
255+
Same point as for registries.d. Make it support the new lookup locations. Note this isn't a
256+
traditional config file but rather each entry is a directory with the registry name and then
257+
contains certificates. So we should share code for the same lookup locations but there will
258+
not be much code sharing otherwise for this.
259+
260+
There is also an open issue for proper XDG_CONFIG_HOME support [2] which should get fixed
261+
as part of this.
262+
263+
##### policy.json
264+
265+
This is a json file so I don't think the normal drop-in logic would be particular useful here.
266+
For consistency it should read also `/usr/share/containers/policy.json` if the /etc file doesn't
267+
exists.
268+
269+
It is also missing the XDG_CONFIG_HOME support[3] so fix that as well.
270+
271+
We got an issue for drop-in support [5]. However I explicitly consider this out of scope for now
272+
due the increased complexity and short time line for podman 6. Drop-in support could still be
273+
added later as I don't consider that a breaking change, it only adds new functionality.
274+
275+
## **Use cases**
276+
277+
A better way to configure podman and a better understanding for users how to do it without having
278+
to worry that each config file behaves differently.
279+
Since we then have only once place that defines the load order we can have a single man page
280+
documenting the load order as described above. All the config files man pages can then just
281+
refer to that and we don't have to duplicate so much docs.
282+
283+
By adding `/usr/share/containers` locations for all config files vendors can properly ship default
284+
configurations there without causing package/user conflicts in `/etc` when admins also want to set
285+
a default config.
286+
This helps "Image Mode" or "Atomic" distributions which tend to prefer using /usr for configuration
287+
when possible, i.e.
288+
https://bootc-dev.github.io/bootc/building/guidance.html#configuration-in-usr-vs-etc
289+
Given the increased importance of podman on such distributions it makes sense to support /usr configs
290+
universally.
291+
292+
## **Target Podman Release**
293+
294+
6.0 (Because this is a breaking change a major release is required and this work must be finished in time)
295+
296+
## **Link(s)**
297+
298+
299+
- [1] https://github.com/containers/podman/issues/27227
300+
- [2] https://github.com/containers/container-libs/issues/183
301+
- [3] https://github.com/containers/container-libs/issues/202
302+
- [4] https://github.com/containers/buildah/issues/6468
303+
- [5] https://github.com/containers/container-libs/issues/527
304+
- https://github.com/containers/container-libs/issues/164
305+
- https://github.com/containers/container-libs/issues/476
306+
307+
- https://github.com/containers/container-libs/issues/234
308+
309+
310+
## **Stakeholders**
311+
312+
313+
- [x] Podman Users
314+
- [x] Podman Developers
315+
- [x] Buildah Users
316+
- [x] Buildah Developers
317+
- [x] Skopeo Users
318+
- [x] Skopeo Developers
319+
- [x] Podman Desktop
320+
- [x] CRI-O
321+
- [x] Storage library
322+
- [x] Image library
323+
- [x] Common library
324+
- [ ] Netavark and aardvark-dns
325+
326+
## ** Assignee(s) **
327+
328+
- Paul Holzinger (@Luap99)
329+
330+
## **Impacts**
331+
332+
### **CLI**
333+
334+
The cli should not change based on this.
335+
336+
### **Libpod**
337+
338+
No changes to libpod.
339+
340+
### **Others**
341+
342+
The major work will happen in the container-libs monorepo as this contains the file parsing logic for all.
343+
344+
## **Further Description (Optional):**
345+
346+
<!--
347+
Is there anything not covered above that needs to be mentioned?
348+
-->
349+
350+
## **Test Descriptions (Optional):**
351+
352+
The code should be designed in a way to be unit testable and that they get parsed in the right order.

0 commit comments

Comments
 (0)