Skip to content

Commit

Permalink
fix: proper cleanup for networks; ensure cleanup of resources
Browse files Browse the repository at this point in the history
Cause: The code was not managing network systemd quadlet units.

Consequence: Network systemd quadlet units were not being stopped and
disabled.  Subsequent runs would fail due to the network units not
being cleaned up properly.

Fix: The role manages network systemd quadlet units, including stopping
and removing.

Result: Systemd quadlet network units are properly cleaned up.

In addition - improve the removal of all types of quadlet resources,
and include code which can be used to test and debug quadlet resource
removal.
  • Loading branch information
richm committed Jul 9, 2024
1 parent 75585a0 commit 7ebe99e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 52 deletions.
2 changes: 1 addition & 1 deletion tasks/cancel_linger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
when: __podman_xdg_stat.stat.exists

- name: Cancel linger if no more resources are in use
command: loginctl disable-linger {{ __podman_linger_user }}
command: loginctl disable-linger {{ __podman_linger_user | quote }}
when:
- __podman_xdg_stat.stat.exists
- __podman_container_info.containers | length == 0
Expand Down
119 changes: 73 additions & 46 deletions tasks/cleanup_quadlet_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,6 @@
vars:
__service_error: Could not find the requested service

- name: See if quadlet file exists
stat:
path: "{{ __podman_quadlet_file }}"
register: __podman_network_stat
when: __podman_quadlet_type == "network"

- name: Get network quadlet network name
when:
- __podman_quadlet_type == "network"
- __podman_network_stat.stat.exists
block:
- name: Create tempdir
tempfile:
prefix: podman_
suffix: _lsr.ini
state: directory
register: __podman_network_tmpdir
delegate_to: localhost

- name: Fetch the network quadlet
fetch:
dest: "{{ __podman_network_tmpdir.path }}/network.ini"
src: "{{ __podman_quadlet_file }}"
flat: true

- name: Get the network name
set_fact:
__podman_network_name: "{{
lookup('ini', 'NetworkName section=Network file=' ~
__podman_network_tmpdir.path ~ '/network.ini') }}"
always:
- name: Remove tempdir
file:
path: "{{ __podman_network_tmpdir.path }}"
state: absent
delegate_to: localhost

- name: Remove quadlet file
file:
path: "{{ __podman_quadlet_file }}"
Expand All @@ -91,22 +54,86 @@
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: Prune images no longer in use
command: podman image prune -f
command: podman image prune --all -f
changed_when: true
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: Remove networks no longer in use
command: podman network prune -f
changed_when: true
when: __podman_quadlet_type == "network"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
changed_when: true
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: Remove network
command: podman network rm {{ __name | quote }}
- name: Remove volumes no longer in use
command: podman volume prune -f
changed_when: true
when: __podman_quadlet_type == "network"
when: __podman_quadlet_type == "volume"
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - images
when: __podman_test_debug | d(false)
command: podman images -n
register: __podman_test_debug_images
changed_when: false
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - volumes
when: __podman_test_debug | d(false)
command: podman volume ls -n
register: __podman_test_debug_volumes
changed_when: false
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - containers
when: __podman_test_debug | d(false)
command: podman ps --noheading
register: __podman_test_debug_containers
changed_when: false
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - networks
when: __podman_test_debug | d(false)
command: podman network ls -n -q
register: __podman_test_debug_networks
changed_when: false
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - secrets
when: __podman_test_debug | d(false)
command: podman secret ls -n -q
register: __podman_test_debug_secrets
changed_when: false
no_log: true
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"

- name: For testing and debugging - services
when: __podman_test_debug | d(false)
service_facts:
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
vars:
__name: "{{ __podman_network_name if
__podman_network_name | d('') | length > 0
else 'systemd-' ~ __podman_quadlet_name }}"
environment:
XDG_RUNTIME_DIR: "{{ __podman_xdg_runtime_dir }}"
2 changes: 1 addition & 1 deletion tasks/create_update_quadlet_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
become: "{{ __podman_rootless | ternary(true, omit) }}"
become_user: "{{ __podman_rootless | ternary(__podman_user, omit) }}"
loop: "{{ __podman_images | unique | list }}"
no_log: true
no_log: false

- name: Ensure the quadlet directory is present
file:
Expand Down
2 changes: 2 additions & 0 deletions tasks/handle_quadlet_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@
if __podman_quadlet_type in ['container', 'kube']
else __podman_quadlet_name ~ '-volume.service'
if __podman_quadlet_type in ['volume']
else __podman_quadlet_name ~ '-network.service'
if __podman_quadlet_type in ['network']
else none }}"

- name: Set per-container variables part 4
Expand Down
2 changes: 1 addition & 1 deletion tasks/manage_linger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- __podman_item_state | d('present') != 'absent'
block:
- name: Enable linger if needed
command: loginctl enable-linger {{ __podman_user }}
command: loginctl enable-linger {{ __podman_user | quote }}
when: __podman_rootless | bool
args:
creates: /var/lib/systemd/linger/{{ __podman_user }}
Expand Down
51 changes: 48 additions & 3 deletions tests/tests_quadlet_basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,34 @@
register: __stat
failed_when: not __stat.stat.exists

# must clean up networks last - cannot remove a network
# in use by a container - using reverse assumes the network
# is defined first in the list
# must clean up in the reverse order of creating - and
# ensure networks are removed last
- name: Cleanup user
include_role:
name: linux-system-roles.podman
vars:
__podman_test_debug: true
podman_run_as_user: user_quadlet_basic
__absent: {"state":"absent"}
podman_secrets: "{{ __podman_secrets | map('combine', __absent) |
list }}"
podman_quadlet_specs: "{{ __podman_quadlet_specs | reverse |
map('combine', __absent) | list }}"

- name: Ensure no resources
assert:
that:
- __podman_test_debug_images.stdout == ""
- __podman_test_debug_networks.stdout_lines |
reject("match", "^podman$") |
reject("match", "^podman-default-kube-network$") |
list | length == 0
- __podman_test_debug_volumes.stdout == ""
- __podman_test_debug_containers.stdout == ""
- __podman_test_debug_secrets.stdout == ""
- ansible_facts["services"].keys() | select("match", "quadlet") |
list | length == 0

- name: Ensure no linger
stat:
path: /var/lib/systemd/linger/user_quadlet_basic
Expand Down Expand Up @@ -236,6 +250,22 @@
changed_when: false

rescue:
- name: Debug3
shell: |
set -x
set -o pipefail
exec 1>&2
#podman volume rm --all
#podman network prune -f
podman volume ls
podman network ls
podman secret ls
podman container ls
podman pod ls
podman images
systemctl list-units | grep quadlet
changed_when: false

- name: Check AVCs
command: grep type=AVC /var/log/audit/audit.log
changed_when: false
Expand Down Expand Up @@ -270,12 +300,27 @@
include_role:
name: linux-system-roles.podman
vars:
__podman_test_debug: true
__absent: {"state":"absent"}
podman_secrets: "{{ __podman_secrets |
map('combine', __absent) | list }}"
podman_quadlet_specs: "{{ __podman_quadlet_specs | reverse |
map('combine', __absent) | list }}"

- name: Ensure no resources
assert:
that:
- __podman_test_debug_images.stdout == ""
- __podman_test_debug_networks.stdout_lines |
reject("match", "^podman$") |
reject("match", "^podman-default-kube-network$") |
list | length == 0
- __podman_test_debug_volumes.stdout == ""
- __podman_test_debug_containers.stdout == ""
- __podman_test_debug_secrets.stdout == ""
- ansible_facts["services"].keys() | select("match", "quadlet") |
list | length == 0

rescue:
- name: Dump journal
command: journalctl -ex
Expand Down
24 changes: 24 additions & 0 deletions tests/tests_quadlet_demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
include_role:
name: linux-system-roles.podman
vars:
__podman_test_debug: true
__absent: {"state":"absent"}
podman_quadlet_specs: "{{ __podman_quadlet_specs |
reverse | map('combine', __absent) | list }}"
Expand All @@ -161,7 +162,30 @@
- name: envoy-certificates
state: absent

- name: Ensure no resources
assert:
that:
- __podman_test_debug_images.stdout == ""
- __podman_test_debug_networks.stdout_lines |
reject("match", "^podman$") |
reject("match", "^podman-default-kube-network$") |
list | length == 0
- __podman_test_debug_volumes.stdout == ""
- __podman_test_debug_containers.stdout == ""
- __podman_test_debug_secrets.stdout == ""
- ansible_facts["services"].keys() | select("match", "quadlet") |
list | length == 0
rescue:
- name: Debug
shell: |
exec 1>&2
set -x
systemctl list-units --plain -l --all | grep quadlet || :
systemctl list-unit-files --all | grep quadlet || :
systemctl list-units --plain --failed -l --all | grep quadlet || :
journalctl -u quadlet-demo-mysql.service || :
systemctl status quadlet-demo-mysql.service || :
- name: Get journald
command: journalctl -ex
changed_when: false
Expand Down

0 comments on commit 7ebe99e

Please sign in to comment.