Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to convert relative host paths into absolute paths #52

Closed
rugk opened this issue Jan 10, 2024 · 3 comments · Fixed by #55
Closed

Add option to convert relative host paths into absolute paths #52

rugk opened this issue Jan 10, 2024 · 3 comments · Fixed by #55
Labels
enhancement New feature or request
Milestone

Comments

@rugk
Copy link
Contributor

rugk commented Jan 10, 2024

Problem: If not given, podman seems to assume $HOME/.config/containers/systemd as your home directory. This is bad if you use any relative paths in your compose file (e.g. I assume).

STR

When you read this: Pay attention to the places ./config appears. ./config is a configuration directory with lots of stuff in there, but could be anything (like a file) for the sake.

Have this docker-compose.yml YAML:

version: "2.1"
services:
  grocy:
    image: lscr.io/linuxserver/grocy:latest
    container_name: grocy
    environment:
      # - PUID=1000
      # - PGID=1000
      - TZ=Europe/Berlin
    volumes:
      - ./config:/config:Z
    ports:
      - 9283:80
    restart: unless-stopped
    labels:
      - io.containers.autoupdate=registry

Do all the processing chain to get it into a service and try to start it:

$ podlet -f "$HOME/.config/containers/systemd" --install compose docker-compose.yml
systemctl --user daemon-reload
systemctl --user start service-name
systemctl --user status service-name

Debugging

When you look into the log, you'll see (apart from other stuff) this:

$ journalctl --user -xeu grocy.service
**snip**
*** *** grocy[70221]: Error: statfs ***/.config/containers/systemd/config: no such file or directory
**snip**

Now where does that strange ***/.config/containers/systemd/config come from?
Tip: It has nothing to do with system.

$ /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
quadlet-generator[70732]: Loading source unit file *****/.config/containers/systemd/grocy.container
---grocy.service---
[X-Container]
AutoUpdate=registry
ContainerName=grocy
Environment=TZ=Europe/Berlin
Image=lscr.io/linuxserver/grocy:latest
PublishPort=9283:80
Volume=./config:/config:Z

[Service]
Restart=always
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -f -i --cidfile=%t/%N.cid
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name=grocy --cidfile=%t/%N.cid --replace --rm --cgroups=split --sdnotify=conmon -d -v *****/.config/containers/systemd/config:/config:Z --label io.containers.autoupdate=registry --publish 9283:80 --env TZ=Europe/Berlin lscr.io/linuxserver/grocy:latest

[Install]
WantedBy=default.target

[Unit]
SourcePath=*****/.config/containers/systemd/grocy.container
RequiresMountsFor=%t/containers
RequiresMountsFor=*****/.config/containers/systemd/config

The solution: ***/.config/containers/systemd/config is our ./config from above, apparently!

Somehow the podman-systemd-generator or so always assumes $HOME/.config/containers/systemd as it's home directory.

Proposed solution

Always include WorkingDir=… with the absolute path to the $PWD when podlet is executed, to make sure it works.

Workaround

I guess adding -w "$PWD" respectively working_dir: $PWD should solve it, too.

Edit: Ah no working_dir seems to be the location inside the container, not the one for podman itself, i.e. when creating volumes.

System

$ podlet --version
podlet 0.2.3 # (from quay.io)
$ podman --version
podman version 4.7.2

Fedora CoreOS v39.20231204.3.3

Misc

AFAIK this should also affect your Readme caddy example, which also uses ./Caddyfile and ./caddy_data.

@k9withabone
Copy link
Member

Podlet does a literal translation when creating quadlet files. If you look at the quadlet docs, in the [Container] section, the docs for the Volume= option say that relative paths are resolved relative to the location of the unit file.

A --canonicalize-system-paths option could be added which transforms system paths (like directories for volumes and device mounts) into their canonical form based on the current working directory when podlet is run. However, this would require that the file exists, see std::fs::canonicalize().

@rugk
Copy link
Contributor Author

rugk commented Jan 12, 2024

Ah thanks, I see, but the “location of the unit file” changes, during that setup, which breaks it in my case.

--canonicalize-system-paths

A good idea, however, if the file needs to exist maybe not optimal then?

How about an option --expand-pwd or so that just expands the ./local file paths to the one where the docker-compose file lies? Because this would be the 100% (compatible) equivalent to when you run docker compose. There files neither need to exist and they are relative to the path of the docker-compose file.

After all podman does not need a full canonical (real) path (it can have ../ in there), it just needs the correct PWD? A path /home/somename/absolutepath-to-docker-project/named-project/../other-name/config.yml is totally fine e.g.
That's why my original proposal just involved trying to change the pwd.

@k9withabone
Copy link
Member

What do you think of a podlet --absolute-host-paths option whose --help reads as follows:

--absolute-host-paths [<RESOLVE_DIR>]

Convert relative host paths to absolute paths

Relative host paths in generated quadlet files are resolved using the given directory, the current working directory, or, for podlet compose, the parent directory of the given compose file.

All host paths are also cleaned to remove interior /../, /./, and //.

Returns an error if the current working directory cannot be read or if the given directory path is not absolute.

Then the implementation uses something like this with the path-clean crate:

use std::{
    borrow::Cow,
    path::{Path, PathBuf},
};

use path_clean::PathClean;

fn absolute_clean_path(current_dir: &Path, path: &Path) -> PathBuf {
    let path: Cow<Path> = if path.is_absolute() {
        path.into()
    } else {
        current_dir.join(path).into()
    };

    path.clean()
}

@k9withabone k9withabone changed the title Current working directory should (always) be passed as it othwerwise causes issues Add option to convert relative host paths into absolute paths Jan 13, 2024
@k9withabone k9withabone added the enhancement New feature or request label Jan 13, 2024
@k9withabone k9withabone added this to the v0.2.4 milestone Jan 15, 2024
@k9withabone k9withabone linked a pull request Jan 22, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants