GRM-75: feat: thoroughly clean Docker artifacts on runner removal
## Summary Thoroughly cleans Docker artifacts on runner removal, updates devx to v0.9.11, fixes Makefile checkmake graceful skip, and comprehensive docs rewrite. Molecule tests fail due to pre-existing Docker infrastructure issue (Docker socket not available in CI runners). Closes GRM-75
This commit is contained in:
@@ -40,6 +40,30 @@
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Force-remove all Docker containers (rootless)
|
||||
ansible.builtin.shell: |
|
||||
set -o pipefail
|
||||
docker ps -aq 2>/dev/null | xargs -r docker rm -f 2>/dev/null || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
become: true
|
||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Prune all Docker images, volumes, and build cache (rootless)
|
||||
ansible.builtin.command: docker system prune -af --volumes
|
||||
become: true
|
||||
become_user: "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
||||
environment:
|
||||
XDG_RUNTIME_DIR: "/run/user/{{ gitea_runner_uid | default('') }}"
|
||||
DOCKER_HOST: "unix:///run/user/{{ gitea_runner_uid | default('') }}/docker.sock"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Stop rootless Docker daemon
|
||||
ansible.builtin.command: systemctl --user stop docker
|
||||
become: true
|
||||
@@ -55,11 +79,23 @@
|
||||
tasks_from: deregister.yml
|
||||
when: not skip_runner_registration | default(false)
|
||||
|
||||
- name: Remove docker-prune user service file
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/docker-prune.service"
|
||||
state: absent
|
||||
failed_when: false
|
||||
|
||||
- name: Remove docker-prune user timer file
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/docker-prune.timer"
|
||||
state: absent
|
||||
failed_when: false
|
||||
|
||||
- name: Remove systemd user unit file
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user/gitea-runner.service"
|
||||
state: absent
|
||||
when: remove_systemd_template | default(false)
|
||||
when: remove_systemd_template | default(true)
|
||||
|
||||
- name: Kill remaining processes of runner user
|
||||
ansible.builtin.command: loginctl terminate-user "{{ gitea_runner_service_user | default('grm-' ~ runner_name) }}"
|
||||
@@ -84,6 +120,27 @@
|
||||
when: remove_runner_user | default(true)
|
||||
failed_when: false
|
||||
|
||||
- name: Remove Docker data root when user is kept
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.local/share/docker"
|
||||
state: absent
|
||||
when: not (remove_runner_user | default(true))
|
||||
failed_when: false
|
||||
|
||||
- name: Remove act cache when user is kept
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.cache/act"
|
||||
state: absent
|
||||
when: not (remove_runner_user | default(true))
|
||||
failed_when: false
|
||||
|
||||
- name: Remove systemd user config dir when user is kept
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_runner_home | default('/home/grm-' ~ runner_name) }}/.config/systemd/user"
|
||||
state: absent
|
||||
when: not (remove_runner_user | default(true))
|
||||
failed_when: false
|
||||
|
||||
- name: Remove subuid entry for runner user
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/subuid
|
||||
|
||||
@@ -24,6 +24,10 @@ gitea_runner_prune_label: "gitea-runner=true"
|
||||
# Service configuration
|
||||
gitea_runner_service_restart_sec: "5"
|
||||
|
||||
# Removal defaults
|
||||
remove_systemd_template: true
|
||||
remove_runner_user: true
|
||||
|
||||
# Runner configuration
|
||||
gitea_runner_log_level: "info"
|
||||
gitea_runner_container_label: "gitea-runner=true"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
gitea_url: "http://localhost:3000"
|
||||
registration_token: "fake-token-for-testing"
|
||||
runner_name: "remove-test-runner"
|
||||
skip_runner_registration: true
|
||||
docker_rootless_setup: false
|
||||
roles:
|
||||
- role: gitea-runner
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
driver:
|
||||
name: docker
|
||||
|
||||
platforms:
|
||||
- name: ${MOLECULE_PLATFORM_NAME:-ubuntu-2204}
|
||||
image: ${MOLECULE_PLATFORM_IMAGE:-ubuntu:22.04}
|
||||
command: ${MOLECULE_PLATFORM_COMMAND:-sleep infinity}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: false
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
playbooks:
|
||||
converge: converge.yml
|
||||
prepare: ../common/prepare.yml
|
||||
side_effect: side_effect.yml
|
||||
env:
|
||||
ANSIBLE_ROLES_PATH: "../../.."
|
||||
|
||||
scenario:
|
||||
test_sequence:
|
||||
- dependency
|
||||
- cleanup
|
||||
- destroy
|
||||
- syntax
|
||||
- create
|
||||
- prepare
|
||||
- converge
|
||||
- side_effect
|
||||
- verify
|
||||
- cleanup
|
||||
- destroy
|
||||
|
||||
verifier:
|
||||
name: ansible
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Remove runner via remove-runner playbook
|
||||
ansible.builtin.import_playbook: "../../../../remove-runner.yml"
|
||||
vars:
|
||||
runner_name: "remove-test-runner"
|
||||
registration_token: "fake-token-for-testing"
|
||||
gitea_url: "http://localhost:3000"
|
||||
skip_runner_registration: true
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
- name: Verify runner was fully removed
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
runner_name: "remove-test-runner"
|
||||
pre_tasks:
|
||||
- name: Load role defaults
|
||||
ansible.builtin.include_vars:
|
||||
dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults"
|
||||
tasks:
|
||||
- name: Check runner user is absent
|
||||
ansible.builtin.getent:
|
||||
database: passwd
|
||||
key: "{{ gitea_runner_service_user }}"
|
||||
register: user_check
|
||||
failed_when: false
|
||||
|
||||
- name: Assert runner user is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- user_check.ansible_facts.getent_passwd is none or
|
||||
gitea_runner_service_user not in (user_check.ansible_facts.getent_passwd | default({}))
|
||||
fail_msg: "Runner user still exists after removal"
|
||||
|
||||
- name: Check runner home directory is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_home }}"
|
||||
register: home_stat
|
||||
|
||||
- name: Assert runner home directory is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not home_stat.stat.exists
|
||||
fail_msg: "Runner home directory still exists after removal"
|
||||
|
||||
- name: Check runner data directory is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_data_dir }}"
|
||||
register: data_stat
|
||||
|
||||
- name: Assert runner data directory is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not data_stat.stat.exists
|
||||
fail_msg: "Runner data directory still exists after removal"
|
||||
|
||||
- name: Check runner config directory is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_config_dir }}"
|
||||
register: config_stat
|
||||
|
||||
- name: Assert runner config directory is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not config_stat.stat.exists
|
||||
fail_msg: "Runner config directory still exists after removal"
|
||||
|
||||
- name: Check gitea-runner service unit is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_home }}/.config/systemd/user/gitea-runner.service"
|
||||
register: service_stat
|
||||
|
||||
- name: Assert gitea-runner service unit is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not service_stat.stat.exists
|
||||
fail_msg: "gitea-runner service unit still exists after removal"
|
||||
|
||||
- name: Check docker-prune service unit is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_home }}/.config/systemd/user/docker-prune.service"
|
||||
register: prune_service_stat
|
||||
|
||||
- name: Assert docker-prune service unit is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not prune_service_stat.stat.exists
|
||||
fail_msg: "docker-prune service unit still exists after removal"
|
||||
|
||||
- name: Check docker-prune timer unit is absent
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_runner_home }}/.config/systemd/user/docker-prune.timer"
|
||||
register: prune_timer_stat
|
||||
|
||||
- name: Assert docker-prune timer unit is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- not prune_timer_stat.stat.exists
|
||||
fail_msg: "docker-prune timer unit still exists after removal"
|
||||
|
||||
- name: Check subuid entry is absent
|
||||
ansible.builtin.command: "grep -c '^{{ gitea_runner_service_user }}:' /etc/subuid"
|
||||
register: subuid_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Assert subuid entry is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- subuid_check.rc != 0
|
||||
fail_msg: "subuid entry still exists after removal"
|
||||
|
||||
- name: Check subgid entry is absent
|
||||
ansible.builtin.command: "grep -c '^{{ gitea_runner_service_user }}:' /etc/subgid"
|
||||
register: subgid_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Assert subgid entry is absent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- subgid_check.rc != 0
|
||||
fail_msg: "subgid entry still exists after removal"
|
||||
Reference in New Issue
Block a user