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 support for Podman pod feature and for RHEL/CentOS 8 #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ podman_services:
# If the network does not exist it will be created. This can be used to allow
# multiple services to network with each other. See Networking for caveats
network: somenetwork
# Optional: String name of the pod to be passed to --pod flag.
# If the pod does not exist it will be created.
# If you specify a port map (optional) it will be passed to --publish.
pod:
name: somepod
ports: [80: 80, 443: 443]
# Optional: List of volumes to mount. Takes the same form as the
# podman CLI host-directory:container-directory and as shown below
# mount options are allowed.
Expand Down
13 changes: 9 additions & 4 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
state: directory
path: /etc/containers

# Podman uses this, on at least Ubuntu, to do port publishing.
- name: Ensure iptables is installed
# Podman uses iptables, on at least Ubuntu, to do port publishing.
- name: Ensure required packages are installed
become: true
become_user: root
package:
name: iptables
state: present
name: "{{item}}"
loop:
- iptables
- jq

- name: Include tasks for Red Hat OS family
include_tasks: redhat.yml
Expand All @@ -26,6 +28,9 @@
include_tasks: ubuntu.yml
when: ansible_distribution == "Ubuntu"

- name: Include tasks to create pods
include_tasks: podman_pods.yml

- include_tasks: podman_service.yml
loop: "{{ podman_services }}"
loop_control:
Expand Down
32 changes: 32 additions & 0 deletions tasks/podman_pods.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---

- name: Determine list of required pods and ports
when: service.pod is defined
loop: "{{ podman_services }}"
loop_control:
loop_var: service
set_fact:
podman_pods: "{{ podman_pods | default({}) | combine({service.pod.name: {'name': service.pod.name, 'ports': service.pod.ports | default([]) + (podman_pods[service.pod.name]['ports'] | default([]))}}) }}"

- name: Delete pods with missing port bindings
Copy link
Owner

Choose a reason for hiding this comment

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

The reason I never added pod support was because it would require some gnarly use of the shell module like this.

I keep waiting for upstream Ansible to a module like podman_pod support but that may never happen.

I have two real requests when it comes to this:

  1. What does --pod provide over --network?

  2. If this is to get merged it will need a way to be idempotent. As it stands if I utilize the pod option for any of my services this will always report changed. This breaks one of the core promises of Configuration Management.

Point number 2 is why I never did this, you can do some wicked things with args and shell like:

shell: echo "something" > this_file
args:
    creates: this_file

To make it "idempotent"-ish and I think I'd be willing to accept that but this is already a pretty gnarly script.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I anticipated that it could be problematic to put both changes in one PR and to implement the pod feature in that way. For my use case (Apache Guacamole) I needed an automation to connect 3 containers and publish some of their ports. Neither using pods nor network was possible with the existing Ansible modules, so I picked the pod option.

I don't think we can change the pod feature to have the quality (i.e. idempotency) you require for this project. While we wait for a native Ansible module to cover this feature I'll keep the branch published in case somebody needs to configure pods.

I split the pod feature into #2. Also you can close this PR.

Thanks for your comments and excellent work!

Copy link
Owner

@chasinglogic chasinglogic Jul 29, 2020

Choose a reason for hiding this comment

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

I had a similar problem when trying to deploy Nextcloud without pods I eventually gave up in the end and just exposed all the ports for everything and networked them the old-school way.

I think it's a very valid use case and I would love to see this feature through. With the new Ansible split into modules I'm not even sure where to report this upstream.

I also do not know if we can ship custom modules with roles on Galaxy if so that might be an option?

Perhaps an alternative is to do a little more abusing of the shell module. I've also attempted to make pods be SystemD template units in the past which almost worked but I didn't need pods bad enough to push it over the line.

Copy link
Contributor Author

@jwhb jwhb Jul 29, 2020

Choose a reason for hiding this comment

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

Shipping custom modules on Galaxy is made possible by Collections.

I just stumbled upon this collection on Galaxy: https://galaxy.ansible.com/containers/podman. The project provides additional modules for pods and networks. However it seems that it doesn't let you create networks.

Copy link
Owner

Choose a reason for hiding this comment

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

Perusing the source code I found https://github.com/containers/ansible-podman-collections/blob/master/plugins/modules/podman_network.py

Which does appear to let us create networks. I bet we could pull this as a dependency and make it work.

Choose a reason for hiding this comment

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

Hi @chasinglogic @jwhb ,

I'm really interested in this feature. Do you think this is something you can work on ?

Best,
Jerome

Copy link
Owner

Choose a reason for hiding this comment

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

Hey @jrevillard,

I'm not sure when I can get to working on this

loop: "{{ podman_pods | subelements('ports', skip_missing=yes) }}"
loop_control:
loop_var: pod
when: pod.0.ports is defined
shell: |
podman pod exists {{pod.0.name}} \
&& (podman pod inspect {{pod.0.name}} \
| jq -e ".Config.infraConfig.infraPortBindings[] | select(.hostPort=={{ lookup('dict', pod.1).key }} and .containerPort=={{ lookup('dict', pod.1).value }})" \
|| podman pod rm -f {{pod.0.name}}) || true
register: podman_pod_inspect

- name: Create required pods
loop: "{{podman_pods | dict2items }}"
loop_control:
loop_var: pod
shell: |
podman pod exists "{{pod.key}}" \
|| podman pod create --name "{{pod.key}}" \
{% if pod.value.ports|default([])|length > 0 %}\
--publish {% for port in pod.value.ports %}{{lookup('dict', port).key}}:{{lookup('dict', port).value}}{%- if not loop.last -%},{%- endif -%}{% endfor %}\
{% endif %}
3 changes: 3 additions & 0 deletions templates/podman.service
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ ExecStart=/usr/bin/podman run \
{% if service.network is defined %}
--network {{ service.network }}
{% endif %}
{% if service.pod.name is defined %}
--pod {{ service.pod.name }} \
{% endif %}
{% if service.publish is defined %}
{% for publish in service.publish %}
--publish {{ publish }} \
Expand Down