systemd - do not overwrite unit name when searching (#72985)
* systemd - do not overwrite unit name when searching PR #72702 introduced a bug that changed the unit name when splitting it up for the purpose of searching for the unit. This only happens on unit file templates on systems that have a 5.8 or newer kernel and a version of systemd that does not contain a bugfix that causes systmed to fail to parse dbus. * Use facts rather than a manual probe to determine if systmed is present * Remov unnecessary block * Use vars files instead of set_fact * Add tests for using a templated unit file * Update changelog fragment * Use template to get correct path to sleep binary
This commit is contained in:
parent
13bf04e95a
commit
48803604cd
8 changed files with 135 additions and 60 deletions
4
changelogs/fragments/systemd-preserve-full-unit-name.yml
Normal file
4
changelogs/fragments/systemd-preserve-full-unit-name.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
bugfixes:
|
||||||
|
- >
|
||||||
|
systemd - preserve the full unit name when using a templated service and
|
||||||
|
``systemd`` failed to parse dbus due to a known bug in ``systemd`` (https://github.com/ansible/ansible/pull/72985)
|
|
@ -415,10 +415,10 @@ def main():
|
||||||
elif err and rc == 1 and 'Failed to parse bus message' in err:
|
elif err and rc == 1 and 'Failed to parse bus message' in err:
|
||||||
result['status'] = parse_systemctl_show(to_native(out).split('\n'))
|
result['status'] = parse_systemctl_show(to_native(out).split('\n'))
|
||||||
|
|
||||||
unit, sep, suffix = unit.partition('@')
|
unit_base, sep, suffix = unit.partition('@')
|
||||||
unit_search = '{unit}{sep}*'.format(unit=unit, sep=sep)
|
unit_search = '{unit_base}{sep}'.format(unit_base=unit_base, sep=sep)
|
||||||
(rc, out, err) = module.run_command("{systemctl} list-unit-files '{unit_search}'".format(systemctl=systemctl, unit_search=unit_search))
|
(rc, out, err) = module.run_command("{systemctl} list-unit-files '{unit_search}*'".format(systemctl=systemctl, unit_search=unit_search))
|
||||||
is_systemd = unit in out
|
is_systemd = unit_search in out
|
||||||
|
|
||||||
(rc, out, err) = module.run_command("{systemctl} is-active '{unit}'".format(systemctl=systemctl, unit=unit))
|
(rc, out, err) = module.run_command("{systemctl} is-active '{unit}'".format(systemctl=systemctl, unit=unit))
|
||||||
result['status']['ActiveState'] = out.rstrip('\n')
|
result['status']['ActiveState'] = out.rstrip('\n')
|
||||||
|
|
4
test/integration/targets/systemd/handlers/main.yml
Normal file
4
test/integration/targets/systemd/handlers/main.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- name: remove unit file
|
||||||
|
file:
|
||||||
|
path: /etc/systemd/system/sleeper@.service
|
||||||
|
state: absent
|
|
@ -20,70 +20,73 @@
|
||||||
## systemctl
|
## systemctl
|
||||||
##
|
##
|
||||||
|
|
||||||
- name: check for systemctl command
|
- name: End if this system does not use systemd
|
||||||
shell: which systemctl
|
meta: end_host
|
||||||
failed_when: False
|
when: ansible_facts.service_mgr != 'systemd'
|
||||||
register: systemctl_check
|
|
||||||
|
|
||||||
- meta: end_host
|
- name: Include distribution specific variables
|
||||||
when: systemctl_check.rc != 0
|
include_vars: "{{ lookup('first_found', params) }}"
|
||||||
|
vars:
|
||||||
|
params:
|
||||||
|
files:
|
||||||
|
- "{{ ansible_facts.distribution }}.yml"
|
||||||
|
- "{{ ansible_facts.os_family }}.yml"
|
||||||
|
- default.yml
|
||||||
|
paths:
|
||||||
|
- vars
|
||||||
|
|
||||||
- set_fact:
|
- name: get a list of running services
|
||||||
ssh_service: '{{ "ssh" if ansible_os_family == "Debian" else "sshd" }}'
|
shell: systemctl | fgrep 'running' | awk '{print $1}' | sed 's/\.service//g' | fgrep -v '.' | egrep ^[a-z]
|
||||||
|
register: running_names
|
||||||
|
- debug: var=running_names
|
||||||
|
|
||||||
- block:
|
- name: check running state
|
||||||
- name: get a list of running services
|
systemd:
|
||||||
shell: systemctl | fgrep 'running' | awk '{print $1}' | sed 's/\.service//g' | fgrep -v '.' | egrep ^[a-z]
|
name: "{{ running_names.stdout_lines|random }}"
|
||||||
register: running_names
|
state: started
|
||||||
- debug: var=running_names
|
register: systemd_test0
|
||||||
|
- debug: var=systemd_test0
|
||||||
|
- name: validate results for test0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'systemd_test0.changed is defined'
|
||||||
|
- 'systemd_test0.name is defined'
|
||||||
|
- 'systemd_test0.state is defined'
|
||||||
|
- 'systemd_test0.status is defined'
|
||||||
|
- 'not systemd_test0.changed'
|
||||||
|
- 'systemd_test0.state == "started"'
|
||||||
|
|
||||||
- name: check running state
|
- name: the module must fail when a service is not found
|
||||||
systemd:
|
systemd:
|
||||||
name: "{{ running_names.stdout_lines|random }}"
|
name: '{{ fake_service }}'
|
||||||
state: started
|
state: stopped
|
||||||
register: systemd_test0
|
register: result
|
||||||
- debug: var=systemd_test0
|
ignore_errors: yes
|
||||||
- name: validate results for test0
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'systemd_test0.changed is defined'
|
|
||||||
- 'systemd_test0.name is defined'
|
|
||||||
- 'systemd_test0.state is defined'
|
|
||||||
- 'systemd_test0.status is defined'
|
|
||||||
- 'not systemd_test0.changed'
|
|
||||||
- 'systemd_test0.state == "started"'
|
|
||||||
|
|
||||||
- name: the module must fail when a service is not found
|
- assert:
|
||||||
systemd:
|
that:
|
||||||
name: '{{ fake_service }}'
|
- result is failed
|
||||||
state: stopped
|
- 'result is search("Could not find the requested service {{ fake_service }}")'
|
||||||
register: result
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- assert:
|
- name: the module must fail in check_mode as well when a service is not found
|
||||||
that:
|
systemd:
|
||||||
- result is failed
|
name: '{{ fake_service }}'
|
||||||
- 'result is search("Could not find the requested service {{ fake_service }}")'
|
state: stopped
|
||||||
|
register: result
|
||||||
|
check_mode: yes
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: the module must fail in check_mode as well when a service is not found
|
- assert:
|
||||||
systemd:
|
that:
|
||||||
name: '{{ fake_service }}'
|
- result is failed
|
||||||
state: stopped
|
- 'result is search("Could not find the requested service {{ fake_service }}")'
|
||||||
register: result
|
|
||||||
check_mode: yes
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- assert:
|
- name: check that the module works even when systemd is offline (eg in chroot)
|
||||||
that:
|
systemd:
|
||||||
- result is failed
|
name: "{{ running_names.stdout_lines|random }}"
|
||||||
- 'result is search("Could not find the requested service {{ fake_service }}")'
|
state: started
|
||||||
|
environment:
|
||||||
- name: check that the module works even when systemd is offline (eg in chroot)
|
SYSTEMD_OFFLINE: 1
|
||||||
systemd:
|
|
||||||
name: "{{ running_names.stdout_lines|random }}"
|
|
||||||
state: started
|
|
||||||
environment:
|
|
||||||
SYSTEMD_OFFLINE: 1
|
|
||||||
|
|
||||||
- name: Disable ssh 1
|
- name: Disable ssh 1
|
||||||
systemd:
|
systemd:
|
||||||
|
@ -114,3 +117,5 @@
|
||||||
- systemd_disable_ssh_2 is not changed
|
- systemd_disable_ssh_2 is not changed
|
||||||
- systemd_enable_ssh_1 is changed
|
- systemd_enable_ssh_1 is changed
|
||||||
- systemd_enable_ssh_2 is not changed
|
- systemd_enable_ssh_2 is not changed
|
||||||
|
|
||||||
|
- import_tasks: test_unit_template.yml
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
- name: Copy service file
|
||||||
|
template:
|
||||||
|
src: sleeper@.service
|
||||||
|
dest: /etc/systemd/system/sleeper@.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: remove unit file
|
||||||
|
|
||||||
|
- name: Reload systemd
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: Start and enable service using unit template
|
||||||
|
systemd:
|
||||||
|
name: sleeper@100.service
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
register: template_test_1
|
||||||
|
|
||||||
|
- name: Start and enable service using unit template again
|
||||||
|
systemd:
|
||||||
|
name: sleeper@100.service
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
register: template_test_2
|
||||||
|
|
||||||
|
- name: Stop and disable service using unit template
|
||||||
|
systemd:
|
||||||
|
name: sleeper@100.service
|
||||||
|
state: stopped
|
||||||
|
enabled: no
|
||||||
|
register: template_test_3
|
||||||
|
|
||||||
|
- name: Stop and disable service using unit template again
|
||||||
|
systemd:
|
||||||
|
name: sleeper@100.service
|
||||||
|
state: stopped
|
||||||
|
enabled: no
|
||||||
|
register: template_test_4
|
||||||
|
|
||||||
|
- name:
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- template_test_1 is changed
|
||||||
|
- template_test_1 is success
|
||||||
|
- template_test_2 is not changed
|
||||||
|
- template_test_2 is success
|
||||||
|
- template_test_3 is changed
|
||||||
|
- template_test_4 is not changed
|
|
@ -0,0 +1,8 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Basic service to use as a template
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart={{ sleep_bin_path }} %i
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
2
test/integration/targets/systemd/vars/Debian.yml
Normal file
2
test/integration/targets/systemd/vars/Debian.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ssh_service: ssh
|
||||||
|
sleep_bin_path: /bin/sleep
|
2
test/integration/targets/systemd/vars/default.yml
Normal file
2
test/integration/targets/systemd/vars/default.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ssh_service: sshd
|
||||||
|
sleep_bin_path: /usr/bin/sleep
|
Loading…
Reference in a new issue