Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.9] Handle disabled service units #69804

Merged
merged 1 commit into from Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/ansible/modules/system/service_facts.py
Expand Up @@ -35,7 +35,7 @@
'''

EXAMPLES = '''
- name: populate service facts
- name: Populate service facts
service_facts:

- debug:
Expand Down Expand Up @@ -218,7 +218,11 @@ def gather_services(self):
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
Expand Down
11 changes: 11 additions & 0 deletions 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
@@ -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)
33 changes: 17 additions & 16 deletions test/integration/targets/service_facts/tasks/main.yml
@@ -1,24 +1,25 @@
# 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:

- 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'
32 changes: 32 additions & 0 deletions 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"
26 changes: 26 additions & 0 deletions 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'"
36 changes: 36 additions & 0 deletions 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'"