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

fix: ensure user linger is enabled and disabled correctly #127

Merged
merged 1 commit into from
Feb 8, 2024
Merged
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
5 changes: 5 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,8 @@ podman_pull_image: true
# running the role.
# You can do this on a per-spec basis using continue_if_pull_fails
podman_continue_if_pull_fails: false

# Retry failed pulls
# If true, if a pull attempt fails, it will be retried according
# to the default Ansible `until` behavior.
podman_pull_retry: false
62 changes: 62 additions & 0 deletions tasks/cancel_linger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
# Input:
# * __podman_linger_user - username
- name: Get user information
getent:
database: passwd
key: "{{ __podman_linger_user }}"
fail_key: true
when: "'getent_passwd' not in ansible_facts or
__podman_linger_user not in ansible_facts['getent_passwd']"

- name: Set cancel linger vars
set_fact:
__podman_xdg_runtime_dir: >-
/run/user/{{ ansible_facts["getent_passwd"][__podman_linger_user][1] }}

- name: Stat XDG_RUNTIME_DIR
stat:
path: "{{ __podman_xdg_runtime_dir }}"
register: __podman_xdg_stat

- name: Gather facts for containers
containers.podman.podman_container_info:
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: true
become_user: "{{ __podman_linger_user }}"
when: __podman_xdg_stat.stat.exists
register: __podman_container_info

- name: Gather facts for networks
command: podman network ls -q
register: __podman_networks
changed_when: false
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: true
become_user: "{{ __podman_linger_user }}"
when: __podman_xdg_stat.stat.exists

- name: Gather secrets
command: podman secret ls -n -q
register: __podman_linger_secrets
changed_when: false
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: true
become_user: "{{ __podman_linger_user }}"
when: __podman_xdg_stat.stat.exists

- name: Cancel linger if no more resources are in use
command: loginctl disable-linger {{ __podman_linger_user }}
when:
- __podman_xdg_stat.stat.exists
- __podman_container_info.containers | length == 0
- __podman_networks.stdout_lines | reject("match", "^podman$") |
reject("match", "^podman-default-kube-network$") |
list | length == 0
- __podman_linger_secrets.stdout == ""
changed_when: true
args:
removes: /var/lib/systemd/linger/{{ __podman_user }}
28 changes: 14 additions & 14 deletions tasks/cleanup_kube_spec.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
---
- name: Stat XDG_RUNTIME_DIR
stat:
path: "{{ __podman_xdg_runtime_dir }}"
register: __podman_xdg_stat
when:
- __podman_rootless | bool
- __podman_xdg_runtime_dir | d("") | length > 0

- name: Stop and disable service
systemd:
name: "{{ __podman_service_name.stdout }}"
Expand All @@ -10,6 +18,7 @@
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
register: __podman_service_status
when: not __podman_rootless or __podman_xdg_stat.stat.exists
failed_when:
- __podman_service_status is failed
- not __podman_service_status.stdout is search(__service_error)
Expand All @@ -24,6 +33,7 @@
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
register: __podman_removed
when: not __podman_rootless or __podman_xdg_stat.stat.exists

- name: Remove kubernetes yaml file
file:
Expand All @@ -39,17 +49,7 @@
when: __podman_removed is changed # noqa no-handler
changed_when: true

- name: Gather facts for all containers
containers.podman.podman_container_info:
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
register: __podman_container_info

- name: Cancel linger if no more containers are running
command: loginctl disable-linger {{ __podman_user }}
when:
- __podman_rootless | bool
- __podman_container_info.containers | length == 0
changed_when: true
- name: Manage linger
include_tasks: manage_linger.yml
vars:
__podman_item_state: absent
45 changes: 17 additions & 28 deletions tasks/cleanup_quadlet_spec.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
---
# NOTE: Stopping, disabling, and removing units should also stop
# and remove any pods and containers as well.
- name: Stat XDG_RUNTIME_DIR
stat:
path: "{{ __podman_xdg_runtime_dir }}"
register: __podman_xdg_stat
when:
- __podman_rootless | bool
- __podman_xdg_runtime_dir | d("") | length > 0

- name: Stop and disable service
systemd:
name: "{{ __podman_service_name }}"
scope: "{{ __podman_systemd_scope }}"
state: stopped
enabled: false
force: true
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
register: __podman_service_status
when: __podman_service_name | length > 0
when:
- __podman_service_name | length > 0
- not __podman_rootless or __podman_xdg_stat.stat.exists
failed_when:
- __podman_service_status is failed
- not __podman_service_status.msg is search(__service_error)
Expand All @@ -25,6 +36,11 @@
state: absent
register: __podman_file_removed

- name: Manage linger
include_tasks: manage_linger.yml
vars:
__podman_item_state: absent

- name: Cleanup container resources
when: __podman_file_removed is changed # noqa no-handler
block:
Expand Down Expand Up @@ -53,30 +69,3 @@
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"

- name: Gather facts for all containers
containers.podman.podman_container_info:
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
register: __podman_container_info
no_log: true

- name: Gather facts for networks
command: podman network ls -q
register: __podman_networks
changed_when: false
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"

- name: Cancel linger if no more resources are in use
command: loginctl disable-linger {{ __podman_user }}
when:
- __podman_rootless | bool
- __podman_container_info.containers | length == 0
- __podman_networks.stdout_lines | reject('match', '^podman$') |
list | length == 0
changed_when: true
11 changes: 6 additions & 5 deletions tasks/create_update_kube_spec.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
---
- name: Enable lingering if needed
command: loginctl enable-linger {{ __podman_user }}
when: __podman_rootless | bool
args:
creates: /var/lib/systemd/linger/{{ __podman_user }}
- name: Manage linger
include_tasks: manage_linger.yml
vars:
__podman_item_state: present

- name: Get the host mount volumes
set_fact:
Expand Down Expand Up @@ -47,6 +46,8 @@
password: "{{ container_image_password | default(omit) }}"
register: __podman_image_updated
when: __podman_pull_image | bool
until: __podman_image_updated is success
retries: "{{ podman_pull_retry | ternary(3, 0) }}"
failed_when:
- __podman_image_updated is failed
- not __podman_continue_if_pull_fails
Expand Down
11 changes: 6 additions & 5 deletions tasks/create_update_quadlet_spec.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
---
- name: Enable lingering if needed
command: loginctl enable-linger {{ __podman_user }}
when: __podman_rootless | bool
args:
creates: /var/lib/systemd/linger/{{ __podman_user }}
- name: Manage linger
include_tasks: manage_linger.yml
vars:
__podman_item_state: present

- name: Create host directories
file: "{{ __defaults | combine(podman_host_directories[__hostitem])
Expand Down Expand Up @@ -31,6 +30,8 @@
password: "{{ container_image_password | default(omit) }}"
register: __podman_image_updated
when: __podman_pull_image | bool
until: __podman_image_updated is success
retries: "{{ podman_pull_retry | ternary(3, 0) }}"
failed_when:
- __podman_image_updated is failed
- not __podman_continue_if_pull_fails
Expand Down
55 changes: 35 additions & 20 deletions tasks/handle_secret.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
# SPDX-License-Identifier: MIT
---
- name: Set variables part 0
set_fact:
__podman_secret: "{{ __podman_secret_item |
dict2items | rejectattr('key', 'match', __del_params) |
list | items2dict }}"
vars:
__del_params: "^(run_as_user)$"
no_log: true

- name: Set variables part 1
set_fact:
__podman_user: "{{ __podman_secret_item['run_as_user'] |
Expand All @@ -20,19 +11,43 @@
__podman_xdg_runtime_dir: >-
/run/user/{{ ansible_facts["getent_passwd"][__podman_user][1] }}

- name: Manage linger
include_tasks: manage_linger.yml
vars:
__podman_item_state: "{{ __podman_secret_item.state | d('present') }}"

- name: Stat XDG_RUNTIME_DIR
stat:
path: "{{ __podman_xdg_runtime_dir }}"
register: __podman_xdg_stat
when:
- __podman_rootless | bool
- __podman_xdg_runtime_dir | d("") | length > 0

# if XDG_RUNTIME_DIR does not exist, this means linger
# was already canceled, which means the user is attempting
# to remove more than once
# We use __params here because the Ansible module code will convert a `data`
# parameter string that looks like JSON e.g. {"test": "string"} to a dict or
# list - there seems to be no way to prevent that - but if we construct the
# parameter dict to pass to podman_secret, it seems to preserve the original
# data types
- name: Manage each secret
containers.podman.podman_secret:
data: "{{ __podman_secret.data | string
if 'data' in __podman_secret else omit }}"
driver: "{{ __podman_secret.driver | d(omit) }}"
driver_opts: "{{ __podman_secret.driver_opts | d(omit) }}"
executable: "{{ __podman_secret.executable | d(omit) }}"
force: "{{ __podman_secret.force | d(omit) }}"
name: "{{ __podman_secret.name }}"
skip_existing: "{{ __podman_secret.skip_existing | d(omit) }}"
state: "{{ __podman_secret.state | d(omit) }}"
containers.podman.podman_secret: "{{ __params }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
no_log: true
when: not __podman_rootless or __podman_xdg_stat.stat.exists
no_log: false
vars:
__params: |
{% set rc = {} %}
{% set supported_params = ['data', 'driver', 'driver_opts', 'executable',
'force', 'name', 'skip_existing', 'state'] %}
{% for key in supported_params %}
{% if key in __podman_secret_item %}
{% set _ = rc.__setitem__(key, __podman_secret_item[key]) %}
{% endif %}
{% endfor %}
{{ rc }}
10 changes: 10 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@
selinux_ports: "{{ podman_selinux_ports }}"
when: podman_selinux_ports | length > 0

- name: Keep track of users that need to cancel linger
set_fact:
__podman_cancel_user_linger: []

- name: Handle secrets
include_tasks: handle_secret.yml
loop: "{{ podman_secrets }}"
Expand All @@ -124,3 +128,9 @@
loop: "{{ podman_quadlet_specs }}"
loop_control:
loop_var: __podman_quadlet_spec_item

- name: Cancel linger
include_tasks: cancel_linger.yml
loop: "{{ __podman_cancel_user_linger }}"
loop_control:
loop_var: __podman_linger_user
29 changes: 29 additions & 0 deletions tasks/manage_linger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# Input:
# * __podman_rootless - true or false
# * __podman_user - name of user
# * __podman_item_state - present or absent
# Globals: __podman_cancel_user_linger
- name: Enable linger if needed
when:
- __podman_rootless | bool
- __podman_item_state | d('present') != 'absent'
block:
- name: Enable linger if needed
command: loginctl enable-linger {{ __podman_user }}
when: __podman_rootless | bool
args:
creates: /var/lib/systemd/linger/{{ __podman_user }}

- name: Mark user as not yet needing to cancel linger
set_fact:
__podman_cancel_user_linger: "{{ __podman_cancel_user_linger |
difference([__podman_user]) }}"

- name: Mark user for possible linger cancel
set_fact:
__podman_cancel_user_linger: "{{ __podman_cancel_user_linger |
union([__podman_user]) }}"
when:
- __podman_rootless | bool
- __podman_item_state | d('present') == 'absent'
2 changes: 2 additions & 0 deletions templates/toml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
{{ key }}={{ value }}
{% elif value is mapping and value is not string %}
{{ key }} = [{%- for k in value %} "{{k}}={{value[k]}}", {%- endfor %}]
{% elif value is not string %}
{{ key }} = {{ value }}
{% else %}
{{ key }}="{{ value }}"
{% endif %}
Expand Down
Loading
Loading