Skip to content

Conversation

@Luap99
Copy link
Member

@Luap99 Luap99 commented Aug 6, 2025

see commits

Summary by Sourcery

Centralize and refactor config file path management into a reusable paths struct, add new rootless-specific config search locations, simplify file scanning logic, rename constants to unexported, update module loading to respect the new structure, and adjust tests and documentation accordingly.

New Features:

  • Support rootless-specific config paths under /etc/containers/containers.rootless.conf and per-UID .d directories

Enhancements:

  • Encapsulate config path resolution and search order in a paths struct passed to New/Default functions
  • Refactor systemConfigs, addConfigs, and modules functions to use the new paths struct and simplify directory scanning
  • Rename config path constants to private identifiers and remove deprecated NewConfig helper

Documentation:

  • Update containers.conf man page to include the new rootless config search locations

Tests:

  • Revise existing tests to leverage the paths struct for injective config paths
  • Add search_order_test.go to verify full config file parsing order across UIDs

@openshift-ci openshift-ci bot added the approved label Aug 6, 2025
@sourcery-ai
Copy link

sourcery-ai bot commented Aug 6, 2025

Reviewer's Guide

This PR refactors the container config loading pipeline by introducing an explicit paths abstraction propagated through all loading functions, adds scoped rootless config search locations, simplifies directory scanning logic, restructures module resolution, renames path constants to private identifiers, and updates tests to exercise the new API.

ER diagram for config file search order including new rootless locations

erDiagram
    ETC_CONTAINERS_CONF ||--o{ ETC_CONTAINERS_CONF_D : contains
    ETC_CONTAINERS_CONF ||--o| ETC_CONTAINERS_ROOTLESS_CONF : overrides
    ETC_CONTAINERS_ROOTLESS_CONF ||--o{ ETC_CONTAINERS_ROOTLESS_CONF_D : contains
    ETC_CONTAINERS_ROOTLESS_CONF_D ||--o{ ETC_CONTAINERS_ROOTLESS_CONF_D_UID : contains
    HOME_CONTAINERS_CONF ||--o{ HOME_CONTAINERS_CONF_D : contains
    ETC_CONTAINERS_CONF {
        string path
    }
    ETC_CONTAINERS_CONF_D {
        string path
    }
    ETC_CONTAINERS_ROOTLESS_CONF {
        string path
        int uid
    }
    ETC_CONTAINERS_ROOTLESS_CONF_D {
        string path
    }
    ETC_CONTAINERS_ROOTLESS_CONF_D_UID {
        string path
        int uid
    }
    HOME_CONTAINERS_CONF {
        string path
    }
    HOME_CONTAINERS_CONF_D {
        string path
    }
Loading

ER diagram for module search directories

erDiagram
    PATHS ||--o{ MODULES_HOME : has
    PATHS ||--o{ MODULES_ETC : has
    PATHS ||--o{ MODULES_USR : has
    PATHS {
        string home
        string etc
        string usr
        int uid
    }
    MODULES_HOME {
        string path
    }
    MODULES_ETC {
        string path
    }
    MODULES_USR {
        string path
    }
Loading

Class diagram for new config loading pipeline and paths abstraction

classDiagram
    class Options {
        +bool SetDefault
        +[]string Modules
        +modules(paths *paths) ([]string, error)
    }
    class paths {
        +string usr
        +string etc
        +string home
        +int uid
        +defaultPaths() (*paths, error)
    }
    class Config {
        +LoadedModules() []string
        +Validate() error
        +addCAPPrefix()
    }
    Options --> paths : uses
    Config --> Options : uses
    Options : modules(paths *paths)
    paths : defaultPaths()
    Config : LoadedModules()
    Config : Validate()
    Config : addCAPPrefix()
Loading

Class diagram for updated config file search and module resolution

classDiagram
    class ConfigLoader {
        +New(options *Options) (*Config, error)
        +Default() (*Config, error)
        +newLocked(options *Options, paths *paths) (*Config, error)
        +systemConfigs(paths *paths) ([]string, error)
        +addConfigs(dirPath string, configs []string) ([]string, error)
    }
    class ModuleResolver {
        +moduleDirectories(paths *paths) []string
        +ModuleDirectories() ([]string, error)
    }
    ConfigLoader --> paths : uses
    ConfigLoader --> Options : uses
    ModuleResolver --> paths : uses
Loading

File-Level Changes

Change Details Files
Introduce a paths struct to encapsulate config search paths and propagate it through config loading functions
  • Implemented defaultPaths() to derive usr, etc, home, and uid
  • Updated New, Default, newLocked, systemConfigs, Options.modules, and ModuleDirectories to accept a paths parameter
  • Removed the internal additionalConfigs field from Options
pkg/config/new.go
pkg/config/config_unix.go
pkg/config/config_bsd.go
pkg/config/config_darwin.go
pkg/config/config_linux.go
pkg/config/config_windows.go
Add support for rootless-specific config files under /etc/containers/containers.rootless.conf and its .d and UID subdirectories
  • Extended systemConfigs to include containers.rootless.conf, its .d folder, and per-UID subdirectories when uid > 0
  • Updated documentation to describe new rootless config locations
  • Added search_order_test.go to validate search order across root and rootless scenarios
pkg/config/new.go
docs/containers.conf.5.md
pkg/config/search_order_test.go
Replace WalkDir-based scanning with ReadDir to simplify .conf file discovery
  • Removed filepath.WalkDir implementation in addConfigs
  • Replaced with os.ReadDir and implicit sorting based on entry names
  • Streamlined error handling for non-existent directories
pkg/config/new.go
Refactor module resolution to use the new paths abstraction and remove global variables
  • Removed moduleBaseEtc, moduleBaseUsr, and moduleSubdir globals
  • Introduced moduleDirectories(paths) to build module search paths
  • Updated Options.modules and ModuleDirectories to rely on moduleDirectories(paths)
pkg/config/modules.go
pkg/config/modules_test.go
Update tests to invoke the newLocked API with explicit paths and adjust expectations
  • Replaced calls to New and NewConfig with newLocked(&Options{}, &paths{})
  • Removed assertions on the now-removed additionalConfigs field
  • Adjusted module-loading assertions and absolute path checks
  • Refactored numerous tests to inject a custom paths struct
pkg/config/config_local_test.go
pkg/config/config_test.go
pkg/config/config_remote_test.go
pkg/config/connections_test.go
Rename public config path constants to private for consistent naming
  • Renamed OverrideContainersConfig to overrideContainersConfig
  • Renamed DefaultContainersConfig to defaultContainersConfig
  • Renamed UserOverrideContainersConfig to userOverrideContainersConfig
pkg/config/config_bsd.go
pkg/config/config_darwin.go
pkg/config/config_linux.go
pkg/config/config_windows.go
pkg/config/config.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Luap99 - I've reviewed your changes - here's some feedback:

  • The newLocked function now requires both Options and a paths parameter, which propagates path-resolution concerns throughout the code—consider encapsulating path discovery inside Options or using a builder to simplify these function signatures.
  • There’s overlapping logic in systemConfigs and moduleDirectories for assembling the config search hierarchy; extracting the shared path-merging logic into a common helper would reduce duplication and help keep path resolution consistent.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `newLocked` function now requires both `Options` and a `paths` parameter, which propagates path-resolution concerns throughout the code—consider encapsulating path discovery inside `Options` or using a builder to simplify these function signatures.
- There’s overlapping logic in `systemConfigs` and `moduleDirectories` for assembling the config search hierarchy; extracting the shared path-merging logic into a common helper would reduce duplication and help keep path resolution consistent.

## Individual Comments

### Comment 1
<location> `docs/containers.conf.5.md:15` </location>
<code_context>
 Container engines read the __/usr/share/containers/containers.conf__,
 __/etc/containers/containers.conf__, and __/etc/containers/containers.conf.d/\*.conf__
 for global configuration that effects all users.
+For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
+__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is is the users uid which podman runs under so it can be used to specify a certain config for a only a single user without having to put the config into the users home directory.
 For user specific configuration it reads __\$XDG_CONFIG_HOME/containers/containers.conf__ and
 __\$XDG_CONFIG_HOME/containers/containers.conf.d/\*.conf__ files. When `$XDG_CONFIG_HOME` is not set it falls back to using `$HOME/.config` instead.
</code_context>

<issue_to_address>
Replace 'effects' with 'affects' in both new lines.

In this context, 'affects' is correct because it means to influence users.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
for global configuration that effects all users.
For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
=======
for global configuration that affects all users.
For global configuration that only affects rootless users use __/etc/containers/containers.rootless.conf__,
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `docs/containers.conf.5.md:16` </location>
<code_context>
 __/etc/containers/containers.conf__, and __/etc/containers/containers.conf.d/\*.conf__
 for global configuration that effects all users.
+For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
+__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is is the users uid which podman runs under so it can be used to specify a certain config for a only a single user without having to put the config into the users home directory.
 For user specific configuration it reads __\$XDG_CONFIG_HOME/containers/containers.conf__ and
 __\$XDG_CONFIG_HOME/containers/containers.conf.d/\*.conf__ files. When `$XDG_CONFIG_HOME` is not set it falls back to using `$HOME/.config` instead.
</code_context>

<issue_to_address>
Remove repeated 'is' in 'The UID is is the users uid...'.

It should read: 'The UID is the user's uid...'.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is is the users uid which podman runs under so it can be used to specify a certain config for a only a single user without having to put the config into the users home directory.
=======
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is the user's uid which podman runs under so it can be used to specify a certain config for only a single user without having to put the config into the user's home directory.
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 14 to 15
for global configuration that effects all users.
For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Replace 'effects' with 'affects' in both new lines.

In this context, 'affects' is correct because it means to influence users.

Suggested change
for global configuration that effects all users.
For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
for global configuration that affects all users.
For global configuration that only affects rootless users use __/etc/containers/containers.rootless.conf__,

__/etc/containers/containers.conf__, and __/etc/containers/containers.conf.d/\*.conf__
for global configuration that effects all users.
For global configuration that only effects rootless users use __/etc/containers/containers.rootless.conf__,
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is is the users uid which podman runs under so it can be used to specify a certain config for a only a single user without having to put the config into the users home directory.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Remove repeated 'is' in 'The UID is is the users uid...'.

It should read: 'The UID is the user's uid...'.

Suggested change
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is is the users uid which podman runs under so it can be used to specify a certain config for a only a single user without having to put the config into the users home directory.
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is the user's uid which podman runs under so it can be used to specify a certain config for only a single user without having to put the config into the user's home directory.

Luap99 added 9 commits August 6, 2025 13:38
There is no reason to use filepath.Walk() as we do not want to recurse
at all as such this just makes the code harder to follow.

We can just use os.ReadDir() which also sorts the result already so
there is no need to sort ourselves again.

Signed-off-by: Paul Holzinger <[email protected]>
They should be no need for external consumers to directly access these.

Signed-off-by: Paul Holzinger <[email protected]>
Add three new search location when running rootless for the config file:
- /etc/containers/containers.rootless.conf
- /etc/containers/containers.rootless.conf.d
- /etc/containers/containers.rootless.conf.d/<UID>/

The idea is that this can be set by system administrators to define
default config for all rootless users without setting the options for
the rootful podman. Today /etc/containers/containers.conf is already
used as rootless but its options are also read when podman is used as
root which made it not useable for some users.

Signed-off-by: Paul Holzinger <[email protected]>
Define a helper struct which contains the search paths. That way unit
tests can mock the paths by setting them to something else so we don't
actually end up reading the paths under /usr and /etc and $HOME.

Signed-off-by: Paul Holzinger <[email protected]>
This allows us to fully control the test paths so it doesn't read global
system paths which can break unit tests.

Signed-off-by: Paul Holzinger <[email protected]>
module tests are currently actually broken as rootless as the home dir
is resolved only once and does not take the test override into account.

Instead rewrite modules to use the new paths overwrite struct used by th
emain containers.conf tests already. With that we can mock all paths and
even root/rootless cases while running as the same user.

Signed-off-by: Paul Holzinger <[email protected]>
Signed-off-by: Paul Holzinger <[email protected]>
It is mainly used for tetsing without adding much value. We can check
the loaded modules via the LoadedModules() call on the Config.

Signed-off-by: Paul Holzinger <[email protected]>
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]>
for global configuration that effects all users.
for global configuration that affects all users.
For global configuration that only affects rootless users use __/etc/containers/containers.rootless.conf__,
__/etc/containers/containers.rootless.d/\*.conf__ and __/etc/containers/containers.rootless.d/\$UID/\*.conf__. The UID is the user's uid which podman runs under so it can be used to specify a certain config for only a single user without having to put the config into the user's home directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should split $UID out into a separate sentence. containers.rootless.conf and containers.rootless.conf.d are global configuration. the $UID bit is not, and should be discussed separately.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhh I read globally different here. Globally to me == system directories in this context.

How should this be worded instead then? tbf I think the entire paragraph is just pointless noise and hard to parse. I think just listing each location in the right order like I have in the design docs is likely the most logical.

Copy link
Member

@giuseppe giuseppe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Aug 6, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: giuseppe, Luap99, sourcery-ai[bot]

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@Luap99 Luap99 changed the title pkg/config: rework testsing and add new containers.rootless.conf search location pkg/config: rework testing and add new containers.rootless.conf search location Aug 7, 2025
@baude
Copy link
Member

baude commented Aug 7, 2025

/lgtm

@openshift-ci openshift-ci bot added the lgtm label Aug 7, 2025
@openshift-merge-bot openshift-merge-bot bot merged commit 55585de into containers:main Aug 7, 2025
15 of 16 checks passed
@Luap99 Luap99 deleted the config-dropin branch August 7, 2025 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants