Refactor run-once logic across multiple roles and integrate unified utils/run_once.yml

This commit standardizes all run-once implementations across the following roles:
- desk-git
- dev-fakeroot
- dev-git
- dev-python-yaml
- sys-lock
- sys-svc-certs (wildcard flavor)
- update-apt
- update-pacman
- update-compose
- user-root (moved logic to 01_core.yml + unified run-once handling)
- web-app-matomo
- web-svc-libretranslate

All roles now:
- Use a block guarded by 'run_once_<role>' facts
- Trigger run-once state through utils/run_once.yml
- Optionally disable handler flushing via 'flush_handlers: false'
- Achieve consistent per-host one-time execution semantics

Conversation reference: https://chatgpt.com/share/692c7fbb-ff68-800f-8cb4-4b132cffc8e4
This commit is contained in:
2025-11-30 18:51:40 +01:00
parent e53abbec3b
commit fff7d261a2
14 changed files with 119 additions and 121 deletions

View File

@@ -10,12 +10,12 @@
vars: vars:
package_name: gitconfig package_name: gitconfig
- name: setup git - when: run_once_desk_git is not defined
block:
- name: setup git
command: gitconfig --merge-option rebase --name "{{users.client.full_name}}" --email "{{users.client.email}}" --website "{{users.client.website}}" --signing gpg --gpg-key "{{users.client.gpg}}" command: gitconfig --merge-option rebase --name "{{users.client.full_name}}" --email "{{users.client.email}}" --website "{{users.client.website}}" --signing gpg --gpg-key "{{users.client.gpg}}"
when: run_once_desk_git is not defined
become: false become: false
- name: run the gitconfig tasks once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_desk_git: true flush_handlers: false
when: run_once_desk_git is not defined

View File

@@ -1,11 +1,11 @@
--- ---
- name: Install fakeroot - when: run_once_dev_fakeroot is not defined
block:
- name: Install fakeroot
community.general.pacman: community.general.pacman:
name: fakeroot name: fakeroot
state: present state: present
when: run_once_dev_fakeroot is not defined
- name: run the fakeroot tasks once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_dev_fakeroot: true flush_handlers: false
when: run_once_dev_fakeroot is not defined

View File

@@ -1,10 +1,10 @@
- name: install git - block:
- name: install git
community.general.pacman: community.general.pacman:
name: git name: git
state: present state: present
when: run_once_dev_git is not defined
- name: run the git tasks once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_dev_git: true flush_handlers: false
when: run_once_dev_git is not defined when: run_once_dev_git is not defined

View File

@@ -1,11 +1,11 @@
--- ---
- name: python-yaml install - when: run_once_dev_python_yaml is not defined
block:
- name: python-yaml install
community.general.pacman: community.general.pacman:
name: python-yaml name: python-yaml
state: present state: present
when: run_once_dev_python_yaml is not defined
- name: run the python_yaml tasks once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_dev_python_yaml: true flush_handlers: false
when: run_once_dev_python_yaml is not defined

View File

@@ -1,11 +1,11 @@
--- ---
- name: create {{ PATH_SYSTEM_LOCK_SCRIPT }} - block:
- name: create {{ PATH_SYSTEM_LOCK_SCRIPT }}
copy: copy:
src: sys-lock.py src: sys-lock.py
dest: "{{ PATH_SYSTEM_LOCK_SCRIPT }}" dest: "{{ PATH_SYSTEM_LOCK_SCRIPT }}"
when: run_once_sys_lock is not defined
- name: execute the script copying once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_sys_lock: true flush_handlers: false
when: run_once_sys_lock is not defined when: run_once_sys_lock is not defined

View File

@@ -1,10 +1,14 @@
- name: "Load wildcard certificate for domain" - block:
- name: "Load wildcard certificate for domain"
include_tasks: "dedicated.yml" include_tasks: "dedicated.yml"
vars: vars:
wildcard_domain: true wildcard_domain: true
when: when:
- domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN) - domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN)
- run_once_receive_certificate is not defined - name: run the receive_certificate tasks once
set_fact:
run_once_receive_certificate: true
when: run_once_receive_certificate is not defined
- name: "Load dedicated certificate for domain" - name: "Load dedicated certificate for domain"
include_tasks: "dedicated.yml" include_tasks: "dedicated.yml"
@@ -13,7 +17,3 @@
when: when:
- not (domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN)) - not (domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN))
- name: run the receive_certificate tasks once
set_fact:
run_once_receive_certificate: true
when: run_once_receive_certificate is not defined

View File

@@ -1,11 +1,11 @@
- name: apt update all packages to their latest version - block:
- name: apt update all packages to their latest version
apt: apt:
update_cache: yes update_cache: yes
upgrade: dist upgrade: dist
force_apt_get: yes force_apt_get: yes
when: run_once_update_apt
- name: run the {{ role_name }} logic just once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_update_apt: true flush_handlers: false
when: run_once_update_apt is not defined when: run_once_update_apt is not defined

View File

@@ -7,11 +7,15 @@
- name: "Update with pacman" - name: "Update with pacman"
include_role: include_role:
name: update-pacman name: update-pacman
when: ansible_distribution == 'Archlinux' when:
- ansible_distribution == 'Archlinux'
- run_once_update_pacman is not defined
- name: "Update with apt" - name: "Update with apt"
include_role: include_role:
name: update-apt name: update-apt
when: ansible_distribution == "Debian" when:
- ansible_distribution == "Debian"
- run_once_update_apt is not defined
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml

View File

@@ -1,10 +1,10 @@
- name: update pacman - block:
- name: update pacman
community.general.pacman: community.general.pacman:
update_cache: yes update_cache: yes
upgrade: yes upgrade: yes
when: run_once_update_pacman is not defined
- name: run update pacman once - include_tasks: utils/run_once.yml
set_fact: vars:
run_once_update_pacman: true flush_handlers: false
when: run_once_update_pacman is not defined when: run_once_update_pacman is not defined

View File

@@ -0,0 +1,30 @@
- name: Check if the SSH key for root already exists
ansible.builtin.stat:
path: "/root/.ssh/id_rsa.pub"
register: ssh_key
- block:
- name: Generate a SSH key for root if it does not exist
community.crypto.openssh_keypair:
path: "/root/.ssh/id_rsa"
type: rsa
size: 4096
- name: Display the public SSH key
command: cat /root/.ssh/id_rsa.pub
register: public_key
- name: Output the public SSH key
debug:
msg: "{{ public_key.stdout }}"
when: not ssh_key.stat.exists
- name: "embed user routines for {{ role_path | basename }}"
include_role:
name: user
vars:
user_name: "root"
- include_tasks: utils/run_once.yml
vars:
flush_handlers: false

View File

@@ -1,33 +1,3 @@
- name: Check if the SSH key for root already exists - name: "Execute Role (once)"
ansible.builtin.stat: include_tasks: 01_core.yml
path: "/root/.ssh/id_rsa.pub"
register: ssh_key
- name: Generate a SSH key for root if it does not exist
community.crypto.openssh_keypair:
path: "/root/.ssh/id_rsa"
type: rsa
size: 4096
when: not ssh_key.stat.exists and run_once_user_root is not defined
- name: Display the public SSH key
command: cat /root/.ssh/id_rsa.pub
register: public_key
when: not ssh_key.stat.exists and run_once_user_root is not defined
- name: Output the public SSH key
debug:
msg: "{{ public_key.stdout }}"
when: not ssh_key.stat.exists and run_once_user_root is not defined
- name: "embed user routines for {{ role_path | basename }}"
include_role:
name: user
vars:
user_name: "root"
when: run_once_user_root is not defined
- name: run the user_root tasks once
set_fact:
run_once_user_root: true
when: run_once_user_root is not defined when: run_once_user_root is not defined

View File

@@ -40,3 +40,5 @@
token_auth: "{{ matomo_auth_token }}" token_auth: "{{ matomo_auth_token }}"
return_content: yes return_content: yes
status_code: 200 status_code: 200
- include_tasks: utils/run_once.yml

View File

@@ -1,9 +1,4 @@
--- ---
- name: "construct {{ role_name }}" - name: "Execute Role (once)"
include_tasks: 01_core.yml include_tasks: 01_core.yml
when: run_once_web_app_matomo is not defined when: run_once_web_app_matomo is not defined
- name: run the docker matomo tasks once
set_fact:
run_once_web_app_matomo: true
when: run_once_web_app_matomo is not defined

View File

@@ -1,9 +1,6 @@
- name: "load docker, db and proxy for {{ application_id }}" - block:
- name: "load docker, db and proxy for {{ application_id }}"
include_role: include_role:
name: sys-stk-full-stateful name: sys-stk-full-stateful
when: run_once_web_app_libretranslate is not defined - include_tasks: utils/run_once.yml
when: run_once_web_svc_libretranslate is not defined
- name: run the libretranslate tasks once
set_fact:
run_once_web_app_libretranslate: true
when: run_once_web_app_libretranslate is not defined