diff --git a/changelogs/fragments/enabled_runtime.yml b/changelogs/fragments/enabled_runtime.yml new file mode 100644 index 00000000000..a3166307747 --- /dev/null +++ b/changelogs/fragments/enabled_runtime.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - systemd - extend systemctl is-enabled check to handle "enabled-runtime" (https://github.com/ansible/ansible/pull/77754). diff --git a/lib/ansible/modules/systemd_service.py b/lib/ansible/modules/systemd_service.py index 8340de36ea7..34aef891fd3 100644 --- a/lib/ansible/modules/systemd_service.py +++ b/lib/ansible/modules/systemd_service.py @@ -512,11 +512,15 @@ def main(): # check systemctl result or if it is a init script if rc == 0: - enabled = True - # Check if the service is indirect or alias and if out contains exactly 1 line of string 'indirect'/ 'alias' it's disabled - if out.splitlines() == ["indirect"] or out.splitlines() == ["alias"]: + # https://www.freedesktop.org/software/systemd/man/systemctl.html#is-enabled%20UNIT%E2%80%A6 + if out.rstrip() in ( + "enabled-runtime", # transiently enabled but we're trying to set a permanent enabled + "indirect", # We've been asked to enable this unit so do so despite possible reasons + # that systemctl may have for thinking it's enabled already. + "alias"): # Let systemd handle the alias as we can't be sure what's needed. enabled = False - + else: + enabled = True elif rc == 1: # if not a user or global user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries if module.params['scope'] == 'system' and \ diff --git a/test/integration/targets/systemd/handlers/main.yml b/test/integration/targets/systemd/handlers/main.yml index 57469a04c57..11053b7cb30 100644 --- a/test/integration/targets/systemd/handlers/main.yml +++ b/test/integration/targets/systemd/handlers/main.yml @@ -10,3 +10,8 @@ loop: - dummy.service - dummy.socket + +- name: remove enabled-runtime unit file + file: + path: /etc/systemd/system/baz.service + state: absent diff --git a/test/integration/targets/systemd/tasks/main.yml b/test/integration/targets/systemd/tasks/main.yml index 3c585e07bc8..4dc5d124402 100644 --- a/test/integration/targets/systemd/tasks/main.yml +++ b/test/integration/targets/systemd/tasks/main.yml @@ -120,3 +120,4 @@ - import_tasks: test_unit_template.yml - import_tasks: test_indirect_service.yml +- import_tasks: test_enabled_runtime.yml diff --git a/test/integration/targets/systemd/tasks/test_enabled_runtime.yml b/test/integration/targets/systemd/tasks/test_enabled_runtime.yml new file mode 100644 index 00000000000..dbb41dae5d3 --- /dev/null +++ b/test/integration/targets/systemd/tasks/test_enabled_runtime.yml @@ -0,0 +1,50 @@ +- name: Copy enabled-runtime service file + template: + src: baz.service + dest: /etc/systemd/system/baz.service + owner: root + group: root + mode: '0644' + notify: remove unit file + +- name: Reload systemd + systemd: + daemon_reload: true + +- name: Enable the enabled-runtime service using shell command + shell: systemctl enable --runtime baz + +- name: Enable enabled-runtime service + systemd: + name: baz.service + enabled: true + register: baz_test_1 + +- name: Enable enabled-runtime service again + systemd: + name: baz.service + enabled: true + register: baz_test_2 + +- name: Disable enabled-runtime service + systemd: + name: baz.service + state: stopped + enabled: false + register: baz_test_3 + +- name: Disable enabled-runtime service again + systemd: + name: baz.service + enabled: false + register: baz_test_4 + +- name: + assert: + that: + - baz_test_1 is changed + - baz_test_1 is success + - baz_test_2 is not changed + - baz_test_2 is success + - baz_test_3 is changed + - baz_test_4 is not changed diff --git a/test/integration/targets/systemd/templates/baz.service b/test/integration/targets/systemd/templates/baz.service new file mode 100644 index 00000000000..41604a1741c --- /dev/null +++ b/test/integration/targets/systemd/templates/baz.service @@ -0,0 +1,9 @@ +[Unit] +Description=Baz Server +Documentation=Baz + +[Service] +ExecStart=/bin/yes + +[Install] +WantedBy=default.target