From e9ff2b1411f55f670015048527b1a3a33069b9e8 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Fri, 5 Sep 2025 15:14:17 -0600 Subject: [PATCH] feat: support this role in container builds Feature: Support running the timesync role during container builds. Reason: This is particularly useful for building bootc derivative OSes. Result: These flags enable running the bootc container scenarios in CI, which ensures that the role works in buildah build environment. This allows us to officially support this role for image mode builds. Signed-off-by: Rich Megginson --- handlers/main.yml | 5 ++++ meta/main.yml | 1 + tasks/main.yml | 43 ++++++++++++++++++-------- tasks/set_vars.yml | 21 +++++++++++++ tests/inventory.yaml.j2 | 15 ++++++---- tests/tasks/setup.yml | 33 +++++++------------- tests/tests_chrony.yml | 53 ++++++++++++++++++++++++++------- tests/tests_default_wrapper.yml | 13 ++++++-- tests/tests_ntp.yml | 10 +++++-- tests/tests_ntp_provider1.yml | 1 + tests/tests_ntp_provider2.yml | 3 +- tests/tests_ntp_provider3.yml | 3 +- tests/tests_ntp_provider4.yml | 1 + tests/tests_ntp_provider5.yml | 1 + tests/tests_ntp_provider6.yml | 1 + tests/tests_ntp_ptp.yml | 5 +++- tests/tests_ptp_multi.yml | 11 ++++--- tests/tests_ptp_single.yml | 11 ++++--- 18 files changed, 166 insertions(+), 65 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index f3b555d2..4f9056e5 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -3,21 +3,25 @@ service: name: chronyd state: restarted + when: __timesync_is_booted | d(false) - name: Restart ntpd service: name: ntpd state: restarted + when: __timesync_is_booted | d(false) - name: Restart ptp4l service: name: ptp4l state: restarted + when: __timesync_is_booted | d(false) - name: Restart phc2sys service: name: phc2sys state: restarted + when: __timesync_is_booted | d(false) # wokeignore:rule=master - name: Restart timemaster @@ -25,3 +29,4 @@ # wokeignore:rule=master name: timemaster state: restarted + when: __timesync_is_booted | d(false) diff --git a/meta/main.yml b/meta/main.yml index f11ec9df..bc66dff2 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -18,6 +18,7 @@ galaxy_info: galaxy_tags: - centos - chrony + - containerbuild - el6 - el7 - el8 diff --git a/tasks/main.yml b/tasks/main.yml index c4d331f1..c94cfff6 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -4,6 +4,7 @@ - name: Populate service facts service_facts: + when: __timesync_is_booted | d(false) - name: Set variable `timesync_services` with filtered uniq service names set_fact: @@ -18,6 +19,24 @@ map('regex_replace', '@$', '') | unique | list }}" + when: __timesync_is_booted | d(false) + +- name: Populate service facts when in bootc mode + command: systemctl list-unit-files --type=service -l # noqa command-instead-of-module + register: timesync_services_output + changed_when: false + when: not __timesync_is_booted | d(false) + +- name: Set variable `timesync_services` with filtered uniq service names when in bootc mode + set_fact: + timesync_services: "{{ timesync_services_output.stdout_lines | + select('search', ' enabled$') | + map('regex_replace', ' +enabled$', '') | + map('regex_replace', '[.]service.*$', '') | + map('regex_replace', '@$', '') | + unique | + list }}" + when: not __timesync_is_booted | d(false) - name: Check that variable 'timesync_services' is defined assert: @@ -250,7 +269,7 @@ - name: Disable chronyd service: name: chronyd - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: - timesync_mode != 1 or timesync_ntp_provider != 'chrony' @@ -264,7 +283,7 @@ - name: Disable ntpd service: name: ntpd - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: - timesync_mode != 1 or timesync_ntp_provider != 'ntp' @@ -278,7 +297,7 @@ - name: Disable ntpdate service: name: ntpdate - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: "'ntpdate' in timesync_services" register: __disable_result @@ -290,7 +309,7 @@ - name: Disable sntp service: name: sntp - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: "'sntp' in timesync_services" register: __disable_result @@ -302,7 +321,7 @@ - name: Disable ptp4l service: name: ptp4l - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: - timesync_mode != 2 @@ -316,7 +335,7 @@ - name: Disable phc2sys service: name: phc2sys - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: - timesync_mode != 2 or not timesync_mode2_hwts @@ -334,7 +353,7 @@ __timemstr: timemaster service: name: "{{ __timemstr }}" - state: stopped + state: "{{ 'stopped' if __timesync_is_booted else omit }}" enabled: false when: - timesync_mode != 3 @@ -348,7 +367,7 @@ - name: Enable chronyd service: name: chronyd - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true when: - timesync_mode == 1 @@ -357,7 +376,7 @@ - name: Enable ntpd service: name: ntpd - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true when: - timesync_mode == 1 @@ -366,14 +385,14 @@ - name: Enable ptp4l service: name: ptp4l - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true when: timesync_mode == 2 - name: Enable phc2sys service: name: phc2sys - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true when: - timesync_mode == 2 @@ -384,6 +403,6 @@ service: # wokeignore:rule=master name: timemaster - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true when: timesync_mode == 3 diff --git a/tasks/set_vars.yml b/tasks/set_vars.yml index d391ac0b..9d455a86 100644 --- a/tasks/set_vars.yml +++ b/tasks/set_vars.yml @@ -43,3 +43,24 @@ - "default.yml" paths: - "{{ role_path }}/vars" + +- name: Determine if system is booted with systemd + when: __timesync_is_booted is not defined + block: + - name: Run systemctl + # noqa command-instead-of-module + command: systemctl is-system-running + register: __is_system_running + changed_when: false + failed_when: false + check_mode: false + + - name: Require installed systemd + fail: + msg: "Error: This role requires systemd to be installed." + when: '"No such file or directory" in __is_system_running.msg | d("")' + + - name: Set flag to indicate that systemd runtime operations are available + set_fact: + # see https://www.man7.org/linux/man-pages/man1/systemctl.1.html#:~:text=is-system-running%20output + __timesync_is_booted: "{{ __is_system_running.stdout != 'offline' }}" diff --git a/tests/inventory.yaml.j2 b/tests/inventory.yaml.j2 index c3dffa24..2319aa8c 100644 --- a/tests/inventory.yaml.j2 +++ b/tests/inventory.yaml.j2 @@ -1,11 +1,16 @@ all: hosts: {{ inventory_hostname }}: -{% for key in ["ansible_all_ipv4_addresses", "ansible_all_ipv6_addresses", +{% if __ansible_connection in ["local", "buildah"] %} + ansible_connection: {{ __ansible_connection }} + ansible_host: localhost +{% else %} +{% for key in ["ansible_all_ipv4_addresses", "ansible_all_ipv6_addresses", "ansible_default_ipv4", "ansible_default_ipv6", "ansible_host", "ansible_port", "ansible_ssh_common_args", "ansible_ssh_private_key_file","ansible_user"] %} -{% if key in hostvars[inventory_hostname] %} - {{ key }}: {{ hostvars[inventory_hostname][key] }} -{% endif %} -{% endfor %} +{% if key in hostvars[inventory_hostname] %} + {{ key }}: {{ hostvars[inventory_hostname][key] | to_json }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/tests/tasks/setup.yml b/tests/tasks/setup.yml index c7442bf9..c28be317 100644 --- a/tests/tasks/setup.yml +++ b/tests/tasks/setup.yml @@ -1,16 +1,16 @@ --- # common test setup tasks -- name: Determine if system is ostree and set flag - when: not __timesync_is_ostree is defined - block: - - name: Check if system is ostree - stat: - path: /run/ostree-booted - register: __ostree_booted_stat +- name: Run the role only to get vars needed for validation + include_role: + name: linux-system-roles.timesync + public: true + tasks_from: set_vars.yml - - name: Set flag to indicate system is ostree - set_fact: - __timesync_is_ostree: "{{ __ostree_booted_stat.stat.exists }}" +- name: Skip test on ostree systems if unsupported + meta: end_host + when: + - __timesync_ostree_unsupported | d(false) + - __timesync_is_ostree | d(false) - name: Ensure iproute for gathering default_ipv4 fact package: @@ -25,20 +25,9 @@ when: __required_facts | difference(ansible_facts.keys() | list) | length > 0 vars: - __required_facts: - - default_ipv4 - - distribution - - distribution_major_version - - distribution_version - - os_family + __required_facts: "{{ __timesync_required_facts + ['default_ipv4'] }}" __required_facts_subsets: "{{ ['!all', '!min'] + __required_facts }}" - name: Debug debug: msg: facts {{ ansible_facts | to_nice_json }} - -- name: Skip test on ostree systems if unsupported - meta: end_host - when: - - __timesync_ostree_unsupported | d(false) - - __timesync_is_ostree | d(false) diff --git a/tests/tests_chrony.yml b/tests/tests_chrony.yml index cd3c89fc..c3a51923 100644 --- a/tests/tests_chrony.yml +++ b/tests/tests_chrony.yml @@ -25,16 +25,59 @@ include_role: name: linux-system-roles.timesync public: true + when: not __bootc_validation | d(false) + + - name: Run the role only to get vars needed for validation + include_role: + name: linux-system-roles.timesync + public: true + tasks_from: set_vars.yml + when: __bootc_validation | d(false) - name: Run chrony tests tags: tests::verify block: - name: Flush handlers meta: flush_handlers + when: not __bootc_validation | d(false) - name: Wait for services to start wait_for: timeout: 2 + when: not __bootc_validation | d(false) + + - name: Create QEMU deployment during bootc end-to-end test + delegate_to: localhost + command: "{{ lsr_scriptdir | quote }}/bootc-buildah-qcow.sh {{ ansible_host | quote }}" + changed_when: true + when: ansible_connection == "buildah" + + - name: Check headers for ansible_managed, fingerprint + include_tasks: tasks/check_header.yml + loop: + - "{{ timesync_chrony_conf_path }}" + - "{{ timesync_chrony_sysconfig_path }}" + loop_control: + loop_var: __file + vars: + __fingerprint: "system_role:timesync" + + # check settings in files - only check we can do in non-booted mode + - name: Check for settings in chrony.conf + command: grep -q {{ item | quote }} {{ timesync_chrony_conf_path }} + loop: "{{ timesync_chrony_custom_settings + + (timesync_ntp_servers | selectattr('hostname') | map(attribute='hostname') | list) + + ['makestep ' ~ timesync_step_threshold ~ ' 3'] + + ([sourcedirstr] if sourcedirstr | length > 0 else []) }}" + vars: + sourcedirstr: "{{ 'sourcedir ' ~ timesync_chrony_dhcp_sourcedir + if timesync_dhcp_ntp_servers and timesync_chrony_dhcp_sourcedir + else '' }}" + changed_when: false + + - name: Skip remaining checks unless booted + meta: end_host + when: not __timesync_is_booted - name: Get list of currently used time sources shell: chronyc -n sources || ntpq -pn @@ -58,16 +101,6 @@ that: - "'tracking.log' in logfiles.stdout" - - name: Check headers for ansible_managed, fingerprint - include_tasks: tasks/check_header.yml - loop: - - "{{ timesync_chrony_conf_path }}" - - "{{ timesync_chrony_sysconfig_path }}" - loop_control: - loop_var: __file - vars: - __fingerprint: "system_role:timesync" - always: - name: Cleanup after tests include_tasks: tasks/cleanup.yml diff --git a/tests/tests_default_wrapper.yml b/tests/tests_default_wrapper.yml index 16d28179..a09ac29b 100644 --- a/tests/tests_default_wrapper.yml +++ b/tests/tests_default_wrapper.yml @@ -1,9 +1,14 @@ --- - name: Create static inventory from hostvars tags: - - 'tests::slow' + - tests::slow + - tests::booted hosts: all tasks: + - name: Save connection method + set_fact: + __ansible_connection: "{{ ansible_connection }}" + - name: Create temporary file tempfile: state: file @@ -20,12 +25,14 @@ - name: Run tests_default.yml normally tags: - - 'tests::slow' + - tests::slow + - tests::booted import_playbook: tests_default.yml - name: Run tests_default.yml in check_mode tags: - - 'tests::slow' + - tests::slow + - tests::booted hosts: all tasks: - name: Run ansible-playbook with tests_default.yml in check mode diff --git a/tests/tests_ntp.yml b/tests/tests_ntp.yml index eebf08d8..62b21cc9 100644 --- a/tests/tests_ntp.yml +++ b/tests/tests_ntp.yml @@ -33,15 +33,18 @@ block: - name: Flush handlers meta: flush_handlers + when: __timesync_is_booted - name: Wait for services to start wait_for: timeout: 2 + when: __timesync_is_booted - name: Get list of currently used time sources shell: chronyc -n sources || ntpq -pn register: sources changed_when: false + when: __timesync_is_booted - name: Check time sources assert: @@ -49,17 +52,20 @@ - "'172.16.123.1' in sources.stdout" - "'172.16.123.2' in sources.stdout" - "'172.16.123.3' in sources.stdout" + when: __timesync_is_booted - name: Fetch chrony.conf file slurp: src: /etc/chrony.conf - when: "'LastRx' in sources.stdout" + when: not __timesync_is_booted or "LastRx" in sources.stdout register: chrony_conf_encoded - name: Fetch ntp.conf file slurp: src: /etc/ntp.conf - when: "'LastRx' not in sources.stdout" + when: + - __timesync_is_booted + - "'LastRx' not in sources.stdout" register: ntp_conf_encoded - name: Decode chrony.conf file diff --git a/tests/tests_ntp_provider1.yml b/tests/tests_ntp_provider1.yml index 1c6bb08b..2d74bf2e 100644 --- a/tests/tests_ntp_provider1.yml +++ b/tests/tests_ntp_provider1.yml @@ -28,6 +28,7 @@ post_tasks: - name: Verify provider is working tags: tests::verify + when: __timesync_is_booted block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ntp_provider2.yml b/tests/tests_ntp_provider2.yml index 36b3f01d..cd174c9b 100644 --- a/tests/tests_ntp_provider2.yml +++ b/tests/tests_ntp_provider2.yml @@ -36,12 +36,13 @@ - name: Enable chronyd service: name: chronyd - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true post_tasks: - name: Verify chronyd running tags: tests::verify + when: __timesync_is_booted block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ntp_provider3.yml b/tests/tests_ntp_provider3.yml index 3a5f6e77..71bd3676 100644 --- a/tests/tests_ntp_provider3.yml +++ b/tests/tests_ntp_provider3.yml @@ -36,12 +36,13 @@ - name: Enable ntpd service: name: ntpd - state: started + state: "{{ 'started' if __timesync_is_booted else omit }}" enabled: true post_tasks: - name: Verify ntpd is running tags: tests::verify + when: __timesync_is_booted block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ntp_provider4.yml b/tests/tests_ntp_provider4.yml index b2ebd452..a0df3e03 100644 --- a/tests/tests_ntp_provider4.yml +++ b/tests/tests_ntp_provider4.yml @@ -40,6 +40,7 @@ - name: Verify chronyd is running tags: tests::verify + when: __timesync_is_booted block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ntp_provider5.yml b/tests/tests_ntp_provider5.yml index 378913f6..37ce7b90 100644 --- a/tests/tests_ntp_provider5.yml +++ b/tests/tests_ntp_provider5.yml @@ -40,6 +40,7 @@ - name: Verify ntpd service tags: tests::verify + when: __timesync_is_booted block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ntp_provider6.yml b/tests/tests_ntp_provider6.yml index 2cf0eaee..7a54679b 100644 --- a/tests/tests_ntp_provider6.yml +++ b/tests/tests_ntp_provider6.yml @@ -62,6 +62,7 @@ - name: Verify provider set correctly tags: tests::verify + when: __timesync_is_booted block: - name: Flush handlers meta: flush_handlers diff --git a/tests/tests_ntp_ptp.yml b/tests/tests_ntp_ptp.yml index d98ce1b6..d86ce342 100644 --- a/tests/tests_ntp_ptp.yml +++ b/tests/tests_ntp_ptp.yml @@ -34,6 +34,7 @@ - name: Flush handlers meta: flush_handlers + when: __timesync_is_booted - name: Ensure ethtool is installed package: @@ -49,7 +50,9 @@ changed_when: false - name: Run test - when: "'ware-transmit' in ethtool.stdout" + when: + - __timesync_is_booted + - "'ware-transmit' in ethtool.stdout" block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ptp_multi.yml b/tests/tests_ptp_multi.yml index ad7b6cdc..b334531a 100644 --- a/tests/tests_ptp_multi.yml +++ b/tests/tests_ptp_multi.yml @@ -22,12 +22,13 @@ - name: Run test tags: tests::verify block: - - name: Flush handlers - meta: flush_handlers - - name: Common test setup tasks include_tasks: tasks/setup.yml + - name: Flush handlers + meta: flush_handlers + when: __timesync_is_booted + - name: Ensure ethtool is installed package: name: ethtool @@ -42,7 +43,9 @@ changed_when: false - name: Run test - when: "'ware-transmit' in ethtool.stdout" + when: + - __timesync_is_booted + - "'ware-transmit' in ethtool.stdout" block: - name: Wait for services to start wait_for: diff --git a/tests/tests_ptp_single.yml b/tests/tests_ptp_single.yml index 8f3e61d2..42b39a54 100644 --- a/tests/tests_ptp_single.yml +++ b/tests/tests_ptp_single.yml @@ -13,12 +13,13 @@ - name: Run test tags: tests::verify block: - - name: Flush handlers - meta: flush_handlers - - name: Common test setup tasks include_tasks: tasks/setup.yml + - name: Flush handlers + meta: flush_handlers + when: __timesync_is_booted + - name: Ensure ethtool is installed package: name: ethtool @@ -33,7 +34,9 @@ changed_when: false - name: Run test - when: "'ware-transmit' in ethtool.stdout" + when: + - __timesync_is_booted + - "'ware-transmit' in ethtool.stdout" block: - name: Wait for services to start wait_for: