summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhijeet Kasurde <akasurde@redhat.com>2020-06-17 08:43:06 +0530
committerGitHub <noreply@github.com>2020-06-16 20:13:06 -0700
commit3e363503097ff40f5ee46626acd387fef603c5d0 (patch)
treee594fcd05401c5167f5f969010581b0051e9da79
parent6c9ebd76d1d5dc6e9124c7d0b94e92905c519b65 (diff)
downloadansible-3e363503097ff40f5ee46626acd387fef603c5d0.tar.gz
[2.9] Handle disabled service units (#69804)
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com> (cherry picked from commit 723a904f4e1fc7c17ebdf1a6276f9e4f46e606b2)
-rw-r--r--lib/ansible/modules/system/service_facts.py8
-rw-r--r--test/integration/targets/service_facts/files/ansible.systemd11
-rw-r--r--test/integration/targets/service_facts/files/ansible_test_service.py73
-rw-r--r--test/integration/targets/service_facts/tasks/main.yml33
-rw-r--r--test/integration/targets/service_facts/tasks/systemd_cleanup.yml32
-rw-r--r--test/integration/targets/service_facts/tasks/systemd_setup.yml26
-rw-r--r--test/integration/targets/service_facts/tasks/tests.yml36
7 files changed, 201 insertions, 18 deletions
diff --git a/lib/ansible/modules/system/service_facts.py b/lib/ansible/modules/system/service_facts.py
index 6f425c3aa4..f92ffdb12d 100644
--- a/lib/ansible/modules/system/service_facts.py
+++ b/lib/ansible/modules/system/service_facts.py
@@ -35,7 +35,7 @@ author:
'''
EXAMPLES = '''
-- name: populate service facts
+- name: Populate service facts
service_facts:
- debug:
@@ -218,7 +218,11 @@ class SystemctlScanService(BaseService):
except IndexError:
self.module.fail_json(msg="Malformed output discovered from systemd list-unit-files: {0}".format(line))
if service_name not in services:
- services[service_name] = {"name": service_name, "state": "unknown", "status": status_val, "source": "systemd"}
+ rc, stdout, stderr = self.module.run_command("%s show %s --property=ActiveState" % (systemctl_path, service_name), use_unsafe_shell=True)
+ state = 'unknown'
+ if not rc and stdout != '':
+ state = stdout.replace('ActiveState=', '').rstrip()
+ services[service_name] = {"name": service_name, "state": state, "status": status_val, "source": "systemd"}
else:
services[service_name]["status"] = status_val
return services
diff --git a/test/integration/targets/service_facts/files/ansible.systemd b/test/integration/targets/service_facts/files/ansible.systemd
new file mode 100644
index 0000000000..3466f25a08
--- /dev/null
+++ b/test/integration/targets/service_facts/files/ansible.systemd
@@ -0,0 +1,11 @@
+[Unit]
+Description=Ansible Test Service
+
+[Service]
+ExecStart=/usr/sbin/ansible_test_service "Test\nthat newlines in scripts\nwork"
+ExecReload=/bin/true
+Type=forking
+PIDFile=/var/run/ansible_test_service.pid
+
+[Install]
+WantedBy=multi-user.target
diff --git a/test/integration/targets/service_facts/files/ansible_test_service.py b/test/integration/targets/service_facts/files/ansible_test_service.py
new file mode 100644
index 0000000000..19f1e29138
--- /dev/null
+++ b/test/integration/targets/service_facts/files/ansible_test_service.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+# this is mostly based off of the code found here:
+# http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+import os
+import resource
+import signal
+import time
+
+UMASK = 0
+WORKDIR = "/"
+MAXFD = 1024
+
+if (hasattr(os, "devnull")):
+ REDIRECT_TO = os.devnull
+else:
+ REDIRECT_TO = "/dev/null"
+
+
+def createDaemon():
+ try:
+ pid = os.fork()
+ except OSError as e:
+ raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+ if (pid == 0):
+ os.setsid()
+
+ try:
+ pid = os.fork()
+ except OSError as e:
+ raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+ if (pid == 0):
+ os.chdir(WORKDIR)
+ os.umask(UMASK)
+ else:
+ f = open('/var/run/ansible_test_service.pid', 'w')
+ f.write("%d\n" % pid)
+ f.close()
+ os._exit(0)
+ else:
+ os._exit(0)
+
+ maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
+ if (maxfd == resource.RLIM_INFINITY):
+ maxfd = MAXFD
+
+ for fd in range(0, maxfd):
+ try:
+ os.close(fd)
+ except OSError: # ERROR, fd wasn't open to begin with (ignored)
+ pass
+
+ os.open(REDIRECT_TO, os.O_RDWR)
+ os.dup2(0, 1)
+ os.dup2(0, 2)
+
+ return (0)
+
+
+if __name__ == "__main__":
+
+ signal.signal(signal.SIGHUP, signal.SIG_IGN)
+
+ retCode = createDaemon()
+
+ while True:
+ time.sleep(1000)
diff --git a/test/integration/targets/service_facts/tasks/main.yml b/test/integration/targets/service_facts/tasks/main.yml
index 65220289d9..5a08fad300 100644
--- a/test/integration/targets/service_facts/tasks/main.yml
+++ b/test/integration/targets/service_facts/tasks/main.yml
@@ -1,20 +1,7 @@
# Test playbook for the service_facts module
-# (c) 2017, Adam Miller <admiller@redhat.com>
-
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+# Copyright: (c) 2017, Adam Miller <admiller@redhat.com>
+# Copyright: (c) 2020, Abhijeet Kasurde <akasurde@redhat.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
- name: Gather service facts
service_facts:
@@ -22,3 +9,17 @@
- name: check for ansible_facts.services exists
assert:
that: ansible_facts.services is defined
+
+- name: Test disabled service facts (https://github.com/ansible/ansible/issues/69144)
+ block:
+ - name: display value of ansible_service_mgr
+ debug:
+ msg: 'ansible_service_mgr: {{ ansible_service_mgr }}'
+
+ - name: setup test service script
+ include_tasks: 'systemd_setup.yml'
+
+ - name: execute tests
+ import_tasks: tests.yml
+
+ when: (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and ansible_distribution_major_version is version('7', '>=')) or ansible_distribution == 'Fedora' or (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('15.04', '>=')) or (ansible_distribution == 'Debian' and ansible_distribution_version is version('8', '>=')) or ansible_os_family == 'Suse'
diff --git a/test/integration/targets/service_facts/tasks/systemd_cleanup.yml b/test/integration/targets/service_facts/tasks/systemd_cleanup.yml
new file mode 100644
index 0000000000..b68530b937
--- /dev/null
+++ b/test/integration/targets/service_facts/tasks/systemd_cleanup.yml
@@ -0,0 +1,32 @@
+- name: remove the systemd unit file
+ file:
+ path: /usr/lib/systemd/system/ansible_test.service
+ state: absent
+ register: remove_systemd_result
+
+- name: assert that the systemd unit file was removed
+ assert:
+ that:
+ - "remove_systemd_result.path == '/usr/lib/systemd/system/ansible_test.service'"
+ - "remove_systemd_result.state == 'absent'"
+
+- name: remove python systemd test script file
+ file:
+ path: /usr/sbin/ansible_test_service
+ state: absent
+ register: remove_systemd_binary_result
+
+- name: assert that python systemd test script file was removed
+ assert:
+ that:
+ - "remove_systemd_binary_result.path == '/usr/sbin/ansible_test_service'"
+ - "remove_systemd_binary_result.state == 'absent'"
+
+- name: make sure systemd is reloaded
+ shell: systemctl daemon-reload
+ register: restart_systemd_result
+
+- name: assert that systemd was reloaded
+ assert:
+ that:
+ - "restart_systemd_result.rc == 0"
diff --git a/test/integration/targets/service_facts/tasks/systemd_setup.yml b/test/integration/targets/service_facts/tasks/systemd_setup.yml
new file mode 100644
index 0000000000..85eeed0c7d
--- /dev/null
+++ b/test/integration/targets/service_facts/tasks/systemd_setup.yml
@@ -0,0 +1,26 @@
+- name: install the test daemon script
+ copy:
+ src: ansible_test_service.py
+ dest: /usr/sbin/ansible_test_service
+ mode: '755'
+
+- name: rewrite shebang in the test daemon script
+ lineinfile:
+ path: /usr/sbin/ansible_test_service
+ line: "#!{{ ansible_python_interpreter | realpath }}"
+ insertbefore: BOF
+ firstmatch: yes
+
+- name: install the systemd unit file
+ copy:
+ src: ansible.systemd
+ dest: /etc/systemd/system/ansible_test.service
+ mode: '0644'
+ register: install_systemd_result
+
+- name: assert that the systemd unit file was installed
+ assert:
+ that:
+ - "install_systemd_result.dest == '/etc/systemd/system/ansible_test.service'"
+ - "install_systemd_result.state == 'file'"
+ - "install_systemd_result.mode == '0644'"
diff --git a/test/integration/targets/service_facts/tasks/tests.yml b/test/integration/targets/service_facts/tasks/tests.yml
new file mode 100644
index 0000000000..495b71fbba
--- /dev/null
+++ b/test/integration/targets/service_facts/tasks/tests.yml
@@ -0,0 +1,36 @@
+- name: start the ansible test service
+ service:
+ name: ansible_test
+ enabled: yes
+ state: started
+ register: enable_result
+
+- name: assert that the service was enabled and changes reported
+ assert:
+ that:
+ - "enable_result.enabled == true"
+ - "enable_result is changed"
+
+- name: disable the ansible test service
+ service:
+ name: ansible_test
+ state: stopped
+ enabled: no
+ register: start_result
+
+- name: assert that the service was stopped
+ assert:
+ that:
+ - "start_result.state == 'stopped'"
+ - "start_result is changed"
+
+- name: Populate service facts
+ service_facts:
+
+- name: get ansible_test service's state
+ debug:
+ var: services['ansible_test.service'].state
+
+- name: ansible_test service's running state should be \"inactive\"
+ assert:
+ that: "services['ansible_test.service'].state == 'inactive'"