From e1d36045daaaf2f553e7af33b266c9e351c328db Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Sun, 20 Jul 2025 14:23:08 +0200 Subject: [PATCH] Solved open run_once issues --- roles/cmp-db-docker/tasks/main.yml | 2 + roles/cmp-docker-proxy/tasks/main.yml | 4 +- roles/docker-compose/tasks/main.yml | 2 + roles/pkgmgr-install/tasks/main.yml | 6 +-- roles/srv-proxy-6-6-domain/tasks/main.yml | 2 + roles/srv-proxy-6-6-tls-deploy/tasks/main.yml | 12 ++--- roles/srv-web-6-6-tls-core/tasks/main.yml | 2 + roles/srv-web-7-6-composer/tasks/main.yml | 2 +- roles/srv-web-7-7-inj-css/tasks/main.yml | 16 +++--- roles/srv-web-7-7-inj-iframe/tasks/main.yml | 1 + .../srv-web-7-7-inj-javascript/tasks/main.yml | 1 + roles/srv-web-7-7-inj-matomo/tasks/main.yml | 2 +- roles/svc-db-postgres/tasks/main.yml | 12 ++--- roles/update-apt/tasks/main.yml | 6 +++ roles/update-pip/tasks/main.yml | 1 + roles/user/tasks/main.yml | 1 + tests/integration/test_run_once_tags.py | 53 ++++++++++++++----- 17 files changed, 86 insertions(+), 39 deletions(-) diff --git a/roles/cmp-db-docker/tasks/main.yml b/roles/cmp-db-docker/tasks/main.yml index 57be0ad8..9a7c945c 100644 --- a/roles/cmp-db-docker/tasks/main.yml +++ b/roles/cmp-db-docker/tasks/main.yml @@ -1,3 +1,5 @@ +# run_once_cmp_db_docker + - name: "For '{{ application_id }}': Set database_application_id (Needed due to lazzy loading issue)" set_fact: database_application_id: "{{ application_id }}" diff --git a/roles/cmp-docker-proxy/tasks/main.yml b/roles/cmp-docker-proxy/tasks/main.yml index 1c8f2faf..11639187 100644 --- a/roles/cmp-docker-proxy/tasks/main.yml +++ b/roles/cmp-docker-proxy/tasks/main.yml @@ -1,5 +1,7 @@ +# run_once_cmp_docker_proxy: deactivated + - name: "For '{{ application_id }}': include docker-compose role" - include_role: + include_role: name: docker-compose - name: "For '{{ application_id }}': include role srv-proxy-6-6-domain" diff --git a/roles/docker-compose/tasks/main.yml b/roles/docker-compose/tasks/main.yml index 569f20db..4a22d954 100644 --- a/roles/docker-compose/tasks/main.yml +++ b/roles/docker-compose/tasks/main.yml @@ -1,3 +1,5 @@ +# run_once_docker_compose: deactivate + - name: "Load variables from {{ docker_compose_variable_file }} for whole play" include_vars: "{{ docker_compose_variable_file }}" diff --git a/roles/pkgmgr-install/tasks/main.yml b/roles/pkgmgr-install/tasks/main.yml index 34a68f1e..30a823aa 100644 --- a/roles/pkgmgr-install/tasks/main.yml +++ b/roles/pkgmgr-install/tasks/main.yml @@ -2,7 +2,7 @@ shell: | source ~/.venvs/pkgmgr/bin/activate pkgmgr update pkgmgr - when: run_once_pkgmgr_update is not defined + when: run_once_pkgmgr_install is not defined - name: update {{ package_name }} shell: | @@ -15,5 +15,5 @@ - name: mark pkgmgr update as done set_fact: - run_once_pkgmgr_update: true - when: run_once_pkgmgr_update is not defined \ No newline at end of file + run_once_pkgmgr_install: true + when: run_once_pkgmgr_install is not defined \ No newline at end of file diff --git a/roles/srv-proxy-6-6-domain/tasks/main.yml b/roles/srv-proxy-6-6-domain/tasks/main.yml index 93c0b3d3..93d3e469 100644 --- a/roles/srv-proxy-6-6-domain/tasks/main.yml +++ b/roles/srv-proxy-6-6-domain/tasks/main.yml @@ -1,3 +1,5 @@ +# run_once_srv_proxy_6_6_domain: deactivated + - name: "include role for {{domain}} to receive certificates and do the modification routines" include_role: name: srv-web-7-6-composer diff --git a/roles/srv-proxy-6-6-tls-deploy/tasks/main.yml b/roles/srv-proxy-6-6-tls-deploy/tasks/main.yml index 978b6973..25763ba9 100644 --- a/roles/srv-proxy-6-6-tls-deploy/tasks/main.yml +++ b/roles/srv-proxy-6-6-tls-deploy/tasks/main.yml @@ -5,11 +5,6 @@ when: run_once_nginx_docker_cert_deploy is not defined notify: restart srv-proxy-6-6-tls-deploy.cymais.service -- name: run the nginx_docker_cert_deploy tasks once - set_fact: - run_once_backup_directory_validator: true - when: run_once_nginx_docker_cert_deploy is not defined - - name: "create {{cert_mount_directory}}" file: path: "{{cert_mount_directory}}" @@ -29,4 +24,9 @@ vars: on_calendar: "{{on_calendar_deploy_certificates}}" service_name: "srv-proxy-6-6-tls-deploy.{{application_id}}" - persistent: "true" \ No newline at end of file + persistent: "true" + +- name: run the run_once_srv_proxy_6_6_tls_deploy tasks once + set_fact: + run_once_backup_directory_validator: true + when: run_once_nginx_docker_cert_deploy is not defined \ No newline at end of file diff --git a/roles/srv-web-6-6-tls-core/tasks/main.yml b/roles/srv-web-6-6-tls-core/tasks/main.yml index e28bbfc4..10300faa 100644 --- a/roles/srv-web-6-6-tls-core/tasks/main.yml +++ b/roles/srv-web-6-6-tls-core/tasks/main.yml @@ -1,3 +1,5 @@ +# run_once_srv_web_6_6_tls_core: deactivated + - name: "Include flavor '{{ certbot_flavor }}' for '{{ domain }}'" include_tasks: "{{ role_path }}/tasks/flavors/{{ certbot_flavor }}.yml" diff --git a/roles/srv-web-7-6-composer/tasks/main.yml b/roles/srv-web-7-6-composer/tasks/main.yml index d65fd69d..6f5d29b6 100644 --- a/roles/srv-web-7-6-composer/tasks/main.yml +++ b/roles/srv-web-7-6-composer/tasks/main.yml @@ -1,4 +1,4 @@ -# run_once_srv_web_7_7_inj_compose: deactivated +# run_once_srv_web_7_6_composer: deactivated - name: "include role srv-web-7-7-inj-compose for {{domain}}" include_role: diff --git a/roles/srv-web-7-7-inj-css/tasks/main.yml b/roles/srv-web-7-7-inj-css/tasks/main.yml index 27d8cb94..afb3580f 100644 --- a/roles/srv-web-7-7-inj-css/tasks/main.yml +++ b/roles/srv-web-7-7-inj-css/tasks/main.yml @@ -1,14 +1,12 @@ -# Load this role via srv-web-7-7-inj-compose for consistency - - name: Generate color palette with colorscheme-generator set_fact: color_palette: "{{ lookup('colorscheme', global_css_base_color, count=global_css_count, shades=global_css_shades) }}" - when: run_once_nginx_global_css is not defined + when: run_once_srv_web_7_7_inj_css is not defined - name: Generate inverted color palette with colorscheme-generator set_fact: inverted_color_palette: "{{ lookup('colorscheme', global_css_base_color, count=global_css_count, shades=global_css_shades, invert_lightness=True) }}" - when: run_once_nginx_global_css is not defined + when: run_once_srv_web_7_7_inj_css is not defined - name: Deploy global.css template: @@ -17,20 +15,20 @@ owner: "{{ nginx.user }}" group: "{{ nginx.user }}" mode: '0644' - when: run_once_nginx_global_css is not defined + when: run_once_srv_web_7_7_inj_css is not defined - name: Get stat for global.css stat: path: "{{ global_css_destination }}" register: global_css_stat - when: run_once_nginx_global_css is not defined + when: run_once_srv_web_7_7_inj_css is not defined - name: Set global_css_version set_fact: global_css_version: "{{ global_css_stat.stat.mtime }}" - when: run_once_nginx_global_css is not defined + when: run_once_srv_web_7_7_inj_css is not defined - name: Mark css as done set_fact: - run_once_nginx_global_css: true - when: run_once_nginx_global_css is not defined + run_once_srv_web_7_7_inj_css: true + when: run_once_srv_web_7_7_inj_css is not defined diff --git a/roles/srv-web-7-7-inj-iframe/tasks/main.yml b/roles/srv-web-7-7-inj-iframe/tasks/main.yml index 0298f2ab..8caaa151 100644 --- a/roles/srv-web-7-7-inj-iframe/tasks/main.yml +++ b/roles/srv-web-7-7-inj-iframe/tasks/main.yml @@ -1,3 +1,4 @@ +# run_once_srv_web_7_7_inj_iframe: deactivated - name: "Load iFrame handler JS template for '{{ application_id }}'" set_fact: iframe_code: "{{ lookup('template','iframe-handler.js.j2') }}" diff --git a/roles/srv-web-7-7-inj-javascript/tasks/main.yml b/roles/srv-web-7-7-inj-javascript/tasks/main.yml index ea0842ca..39206a1f 100644 --- a/roles/srv-web-7-7-inj-javascript/tasks/main.yml +++ b/roles/srv-web-7-7-inj-javascript/tasks/main.yml @@ -1,3 +1,4 @@ +# run_once_srv_web_7_7_inj_javascript: deactivated - name: "Load JavaScript code for '{{ application_id }}'" set_fact: javascript_code: "{{ lookup('template', modifier_javascript_template_file) }}" diff --git a/roles/srv-web-7-7-inj-matomo/tasks/main.yml b/roles/srv-web-7-7-inj-matomo/tasks/main.yml index f727d175..6ccf1532 100644 --- a/roles/srv-web-7-7-inj-matomo/tasks/main.yml +++ b/roles/srv-web-7-7-inj-matomo/tasks/main.yml @@ -1,4 +1,4 @@ -# Load this role via srv-web-7-7-inj-compose for consistency +# run_once_srv_web_7_7_inj_matomo: deactivated - name: "Relevant variables for role: {{ role_path | basename }}" debug: diff --git a/roles/svc-db-postgres/tasks/main.yml b/roles/svc-db-postgres/tasks/main.yml index 73589007..95e8484f 100644 --- a/roles/svc-db-postgres/tasks/main.yml +++ b/roles/svc-db-postgres/tasks/main.yml @@ -4,7 +4,7 @@ state: present ipam_config: - subnet: "{{ postgres_subnet }}" - when: run_once_docker_postgres is not defined + when: run_once_svc_db_postgres is not defined - name: Install PostgreSQL docker_container: @@ -28,7 +28,7 @@ retries: 5 start_period: 30s register: setup_postgres_container_result - when: run_once_docker_postgres is not defined + when: run_once_svc_db_postgres is not defined - name: Wait for Postgres inside the container shell: "docker exec {{ postgres_name }} pg_isready -U postgres" @@ -39,13 +39,13 @@ when: - setup_postgres_container_result is defined - setup_postgres_container_result.changed - - run_once_docker_postgres is not defined + - run_once_svc_db_postgres is not defined - name: install python-psycopg2 pacman: name: python-psycopg2 state: present - when: run_once_docker_postgres is not defined + when: run_once_svc_db_postgres is not defined - name: "Initialize database for '{{ database_name }}'" include_tasks: init.yml @@ -53,5 +53,5 @@ - name: Run the docker_postgres tasks once set_fact: - run_once_docker_postgres: true - when: run_once_docker_postgres is not defined \ No newline at end of file + run_once_svc_db_postgres: true + when: run_once_svc_db_postgres is not defined \ No newline at end of file diff --git a/roles/update-apt/tasks/main.yml b/roles/update-apt/tasks/main.yml index f6a7135d..5d063ccc 100644 --- a/roles/update-apt/tasks/main.yml +++ b/roles/update-apt/tasks/main.yml @@ -3,3 +3,9 @@ update_cache: yes upgrade: dist force_apt_get: yes + when: run_once_update_apt + +- name: run the {{ role_name }} logic just once + set_fact: + run_once_update_apt: true + when: run_once_update_apt is not defined \ No newline at end of file diff --git a/roles/update-pip/tasks/main.yml b/roles/update-pip/tasks/main.yml index f70baa78..41136172 100644 --- a/roles/update-pip/tasks/main.yml +++ b/roles/update-pip/tasks/main.yml @@ -1,3 +1,4 @@ +# run_once_update_pip: deactivated # Deactivated due to that it breaks the system # There is no alternative to do the python update # diff --git a/roles/user/tasks/main.yml b/roles/user/tasks/main.yml index eb9201bc..b5a625a8 100644 --- a/roles/user/tasks/main.yml +++ b/roles/user/tasks/main.yml @@ -1,3 +1,4 @@ +# run_once_user: deactivated - name: create .bashrc template: src: "bashrc.j2" diff --git a/tests/integration/test_run_once_tags.py b/tests/integration/test_run_once_tags.py index 35081fc7..6b661d82 100644 --- a/tests/integration/test_run_once_tags.py +++ b/tests/integration/test_run_once_tags.py @@ -15,30 +15,59 @@ def is_under_root_tasks(fpath): return abs_path.startswith(os.path.abspath(ROOT_TASKS_DIR) + os.sep) +import os +import re + def find_role_includes(roles_dir): """ - Yields (filepath, line_number, role_name) for each import_role/include_role usage in roles/, - but ignores anything under the root-level tasks/ dir. + Scan all YAML files under `roles_dir`, skipping any under a top-level `tasks/` directory, + and yield (filepath, line_number, role_name) for each literal import_role/include_role + usage. Dynamic includes using Jinja variables (e.g. {{ ... }}) are ignored. """ for dirpath, _, filenames in os.walk(roles_dir): for fname in filenames: if not fname.endswith(('.yml', '.yaml')): continue + fpath = os.path.join(dirpath, fname) - if is_under_root_tasks(fpath): - continue # Skip root-level tasks dir completely + # Skip any files under the root-level tasks/ directory + if os.path.abspath(fpath).startswith( + os.path.abspath(os.path.join(roles_dir, '..', 'tasks')) + os.sep + ): + continue + try: with open(fpath, 'r', encoding='utf-8') as f: lines = f.readlines() - except Exception: - continue # Ignore unreadable files + except (IOError, OSError): + continue + for idx, line in enumerate(lines): - if 'import_role' in line or 'include_role' in line: - block = line + ''.join(lines[idx+1:idx+5]) - match = re.search(r'name:\s*[\'"]?([\w\-]+)[\'"]?', block) - if match: - role_name = match.group(1) - yield fpath, idx + 1, role_name + if 'import_role' not in line and 'include_role' not in line: + continue + + base_indent = len(line) - len(line.lstrip()) + # Look ahead up to 5 lines for the associated `name:` entry + for nxt in lines[idx+1 : idx+6]: + indent = len(nxt) - len(nxt.lstrip()) + # Only consider more-indented lines (the block under import/include) + if indent <= base_indent: + continue + m = re.match(r'\s*name:\s*[\'"]?([A-Za-z0-9_\-]+)[\'"]?', nxt) + if not m: + continue + + role_name = m.group(1) + # Ignore the generic "user" role include + if role_name == 'user': + break + + # Skip any dynamic includes using Jinja syntax + if '{{' in nxt or '}}' in nxt: + break + + yield fpath, idx + 1, role_name + break def check_run_once_tag(content, role_name):