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 new modules/options for Quadlet #671

Closed
nishipy opened this issue Nov 24, 2023 · 19 comments · Fixed by #722
Closed

Add new modules/options for Quadlet #671

nishipy opened this issue Nov 24, 2023 · 19 comments · Fixed by #722

Comments

@nishipy
Copy link
Contributor

nishipy commented Nov 24, 2023

Is this a BUG REPORT or FEATURE REQUEST? (leave only one on its own line)

/kind feature

Description

Since Podman 4.7.0, the podman generate systemd command has been deprecated. Instead of that, it is recommended to use Quadlet for running containers and pods under systemd.
Now, it's time to consider adding a new module to support Quadlet to run Podman containers under systemd.

More specifically, what we need is:

  1. Generation of podman Quadlet files in podman_container (and others) as we have today with generate_systemd.
  2. Allow podman_container to generate files only, without creating actually containers. (Need to look how easy to do it with current implementation)

Under question:

  1. To check the option to reload systemd in the module as it's suggested here: Run systemctl instead of podman when generating systemd units #585
  2. To have podman_generate_quadlet module
@sshnaidm
Copy link
Member

Yeah, this is a great idea. We need to think how it's better to implement it to avoid problems we have with systemd and its generation.

@nishipy
Copy link
Contributor Author

nishipy commented Dec 5, 2023

Quadlet supports some types of units ([Container], [Kube], [Volume], etc.). If we add podman_container_quadlet, it might be like the following:

- name: Create Quadlet files for container
  podman_container_quadlet:
    description: A minimal container
    image: quay.io/centos/centos:latest
    volume: test.volume:/data
    network: test.network
    exec: sleep 60
    restart: always
    service_spec:
      timeout_start_sec: 900
      exec_start_pre: /usr/share/mincontainer/setup.sh
      wanted_by:
      - multi-user.target
      - default.target

Then, this module will create a Quadlet file:

[Unit]
Description=A minimal container

[Container]
Image=quay.io/centos/centos:latest
Volume=test.volume:/data
Network=test.network
Exec=sleep 60

[Service]
Restart=always
TimeoutStartSec=900
ExecStartPre=/usr/share/mincontainer/setup.sh

[Install]
WantedBy=multi-user.target default.target

After Quadlet files are created, users need to run systemctl daemon-reload via ansible.builtin.systemd_service module in order to create systemd unit files from Quadlet files.

@nishipy
Copy link
Contributor Author

nishipy commented Dec 6, 2023

We can use ansible.builtin.template to create Quadlet files with predefined fields, but modules like podman_container_quadlet can give more flexibility...

@sshnaidm
Copy link
Member

sshnaidm commented Dec 6, 2023

I wonder if it's worth to create a translation module, which just dump yaml to quadlet file. Someone that knows quadlet keys, would probably create the file with templates as you said. Just to translate module values to quadlet seems like effort duplication. But I'm not against the idea, probably module docs would be more thorough for people to understand how to write quadlet(?)
I think we should add quadlet generation to podman_container, podman_volume, podman_kube_play and podman_network modules. Firstly for podman_container - and to have an option to generate a quadlet file with [Service] systemd additions which we have already. Like option generate_quadlet maybe?
Or to have a state generate so the module won't create a container, but only generate files for it. Thinking loudly.

@nishipy
Copy link
Contributor Author

nishipy commented Dec 7, 2023

I think we should add quadlet generation to podman_container, podman_volume, podman_kube_play and podman_network modules

Agreed. This is another option I was thinking of actually. We can add a option such as generate_quadlet with supporting the consistent parameters for podman run/podman kube as the module.

Or to have a state generate so the module won't create a container, but only generate files for it.

I see. It looks better than other ideas to me. I think this is easier for users to understand that as you said the module will create not actual Podman resources (containers, networks, volumes, etc) but quadlet files.

@sshnaidm
Copy link
Member

sshnaidm commented Dec 7, 2023

OK, so let's start summarizing what we need:

  1. Generation of podman Quadlet files in podman_container (and others) as we have today with generate_systemd.
  2. Allow podman_container to generate files only, without creating actually containers. (Need to look how easy to do it with current implementation)

Under question:
3. To check the option to reload systemd in the module as it's suggested here: #585
4. To have podman_generate_quadlet module

@nishipy nishipy changed the title Add a new module for Quadlet Add new modules/options for Quadlet Dec 8, 2023
@nishipy
Copy link
Contributor Author

nishipy commented Dec 12, 2023

  1. Allow podman_container to generate files only, without creating actually containers. (Need to look how easy to do it with current implementation

We have the map for each state and method to be executed, so it seems we can add a new state quadlet and its method here.

def execute(self):
"""Execute the desired action according to map of actions & states."""
states_map = {
'present': self.make_created,
'started': self.make_started,
'absent': self.make_absent,
'stopped': self.make_stopped,
'created': self.make_created,
}

Under question:
3. To check the option to reload systemd in the module as it's suggested here: #585

In general cases, I want to use ansible.builtin.systemd_servicemodule in order to do systemctl-related stuff. However, we always have to run systemctl daemon-reload after quadlet file creation, so it sounds reasonable for me to reload systemd in this case.

@sshnaidm
Copy link
Member

Yeah, as mentioned here I'd like to avoid as possible to trigger systemd in these modules, but seems like the Podman is too tied to it and it's pretty unavoidable. @nishipy would you like to see how to do it in a better way? I think we can use the patch of @nogweii and collaborate on it or to make a new one, he has a lot of things prepared already.
I'll look into implementing Quadlet in common, that should be usable for all modules, in same way generate_systemd is done.

@nishipy
Copy link
Contributor Author

nishipy commented Dec 31, 2023

@sshnaidm Sorry for my late reply

@nishipy would you like to see how to do it in a better way?

yes, let me look into this.

@alorle
Copy link

alorle commented Feb 5, 2024

I am excited about this feature. Has there been any notable progress?

I have some experience with Ansible, but never developed a plugin myself, but if you need some help I'll glad to give you hand.

sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Feb 29, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
sshnaidm added a commit to sshnaidm/ansible-podman-collections that referenced this issue Mar 1, 2024
Fix containers#671
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
@sshnaidm
Copy link
Member

sshnaidm commented Mar 3, 2024

I think I've got the initial version for container and network prepared, please review. It currently creates Quadlet file in given folder, using the usual module configuration. It's possible to add required lines using quadlet_options, see examples in tests:

        quadlet_file_path: /tmp/quadlets/quadlet.container
        quadlet_options:
          - "Label=Test=network"
          - "Label=foo=bar"

All not supported in Quadlet options are going to PodmanArgs section in Quadlet. Some (like --log-level) are going to GlobalArgs.
Running with --diff will print difference in Quadlet configs and also Quadlet config is generated in the end and returned as podman_quadlet variable in results, like I did with systemd.

"podman_actions": [
"podman run --name container122 --publish 9000:80 --publish 9001:8000 --workdir /bin --env FOO=bar=1 --env BAR=foo --env TEST=1 --env BOOL=False --label somelabel=labelvalue --label otheralbe=othervalue --mount type=devpts,destination=/dev/pts --volume /tmp:/data --detach=True alpine:3.12"
],
    "podman_quadlet": "[Container]\nContainerName=container122\nEnvironment=FOO=bar=1\nEnvironment=BAR=foo\nEnvironment=TEST=1\nEnvironment=BOOL=False\nImage=alpine:3.12\nLabel=somelabel=labelvalue\nLabel=otheralbe=othervalue\nMount=type=devpts,destination=/dev/pts\nPublishPort=9000:80\nPublishPort=9001:8000\nVolume=/tmp:/data\nWorkingDir=/bin\n",
    "podman_systemd": {
        "container-container122": "# container-container122.service\n# autogenerated by Podman 4.8.3\n# Sun Mar  3 18:20:34 IST 2024\n\n[Unit]\nDescription=Podman container-container122.service\nDocumentation=man:podman-generate-systemd(1)\nWants=network-online.target\nAfter=network-online.target\nRequiresMountsFor=/run/user/1000/containers\n\n[Service]\nEnvironment=PODMAN_SYSTEMD_UNIT=%n\nRestart=on-failure\nTimeoutStopSec=70\nExecStart=/usr/bin/podman start container122\nExecStop=/usr/bin/podman stop  \\\n\t-t 10 container122\nExecStopPost=/usr/bin/podman stop  \\\n\t-t 10 container122\nPIDFile=/run/user/1000/containers/overlay-containers/c3d91cde84ed953392e22532e3c168466a24a657262869c84d7c4650d4413892/userdata/conmon.pid\nType=forking\n\n[Install]\nWantedBy=default.target\n"
}

Please review and comment, what else is required and desirable?
Systemd reload is not implemented yet, will be the next step I suppose.
@nishipy @alorle and all interested

@sshnaidm
Copy link
Member

sshnaidm commented Mar 3, 2024

Added support for Pod as well

@alorle
Copy link

alorle commented Mar 4, 2024

Great news @sshnaidm !! Firstly, thanks for the effort. I would like to test this, so I can give you some feedback if you want, but I don't know how. Could you point me to the documentation to be able to install your branch into my Ansible project?

@knumskull
Copy link

@alorle you can test the code cloning the branch @sshnaidm created, expecting you will end up in the following directory structure.

.
├── ansible.cfg
├── collections
│   └── ansible_collections
│       └── containers
│           └── podman
└── quadlet-example.yaml
$ git clone -b quadlet git@github.com:sshnaidm/ansible-podman-collections.git collections/containers/podman

With that, basic settings and example could be as follow. The example is taken from documentation made in the quadlet addon by @sshnaidm

$ cat ansible.cfg 
[defaults]
collections_path = collections
$ cat quadlet-example.yaml 
---
- name: Using Podman collection
  hosts: localhost
  tasks:
    - name: Create a Quadlet file
      containers.podman.podman_container:
        name: quadlet-container
        image: nginx
        state: quadlet
        quadlet_file_path: ~/.config/containers/systemd/nginx.container
        device: "/dev/sda:/dev/xvda:rwm"
        ports:
          - "8080:80"
        volumes:
          - "/var/www:/usr/share/nginx/html"

So basic testing works for me.

$ ansible-playbook quadlet-example.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Using Podman collection] ************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create a Quadlet file] **************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP ********************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
$ cat ~/.config/containers/systemd/nginx.container 
[Container]
AddDevice=/dev/sda:/dev/xvda:rwm
ContainerName=quadlet-container
Image=nginx
PublishPort=8080:80
Volume=/var/www:/usr/share/nginx/html

I didn't checked the entire routine, but initially looks good. I will check my entire lab-infra as soon as possible and see if I run into some issues.

@alorle
Copy link

alorle commented Mar 4, 2024

Thanks for the extensive hint @knumskull . This weekend I will try it and give some feedback. Thanks again for the hard work!!

@sshnaidm
Copy link
Member

sshnaidm commented Mar 6, 2024

I wonder if we need to add the generation of systemd unit file themselves, or to leave it to systemd daemon-reload to do.
It's possible by running /usr/libexec/podman/quadlet (one of systemd generators) like: QUADLET_UNIT_DIRS=<Directory> /usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun (docs) . Seems like it can generate only all files in a dir, not one by one, so I doubt it has any value in this module.

@nishipy
Copy link
Contributor Author

nishipy commented Mar 6, 2024

That is certainly true. The /usr/libexec/podman/quadlet will be run for all files in specific directories when systemctl daemon-reload (and during boot).
I think in order to generate regular sysmtemd unit files, it would be better to run systemctl daemon-relaod by include it in this module or by using ansible.builtin.systemd_service module. Considering the point @sshnaidm mentioned (i.e. /usr/libexec/podman/quadlet will search all files in directories and we cannot give a specific file), it might be clearer to ask users to add ansible.builtin.systemd_service after tasks with this module.

@alorle
Copy link

alorle commented Mar 22, 2024

I've been testing it this week and it works perfectly. Thanks for the effort!!

@nishipy
Copy link
Contributor Author

nishipy commented Mar 23, 2024

I think in order to generate regular sysmtemd unit files, it would be better to run systemctl daemon-relaod by include it in this module or by using ansible.builtin.systemd_service module. Considering the point @sshnaidm mentioned (i.e. /usr/libexec/podman/quadlet will search all files in directories and we cannot give a specific file), it might be clearer to ask users to add ansible.builtin.systemd_service after tasks with this module.

Or, how about adding a parameter like daemon_reload (default: false) so that users can switch whether to execute daemon-reload or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants