service_mgr: Detect using symlink if proc/1 and ps fail

* runit and other alternative service managers tend to work via symlink so this covers most of em
* Fixes #74866.
This commit is contained in:
Johannes Heimansberg 2021-06-03 15:59:31 +02:00 committed by GitHub
parent 9c718ccc42
commit b023f34f4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 0 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- module_utils - detect symlinked init systems, even if unable to read /proc/1/comm (https://github.com/ansible/ansible/issues/74866).

View file

@ -98,6 +98,9 @@ class ServiceMgrFactCollector(BaseFactCollector):
if proc_1 == "COMMAND\n":
proc_1 = None
if proc_1 is None and os.path.islink('/sbin/init'):
proc_1 = os.readlink('/sbin/init')
# FIXME: empty string proc_1 staus empty string
if proc_1 is not None:
proc_1 = os.path.basename(proc_1)

View file

@ -401,6 +401,36 @@ class TestServiceMgrFacts(BaseFactsTest):
self.assertIsInstance(facts_dict, dict)
self.assertEqual(facts_dict['service_mgr'], 'service')
@patch('ansible.module_utils.facts.system.service_mgr.get_file_content', return_value='runit-init')
@patch('ansible.module_utils.facts.system.service_mgr.os.path.islink', side_effect=lambda x: x == '/sbin/init')
@patch('ansible.module_utils.facts.system.service_mgr.os.readlink', side_effect=lambda x: '/sbin/runit-init' if x == '/sbin/init' else '/bin/false')
def test_service_mgr_runit(self, mock_gfc, mock_opl, mock_orl):
# /proc/1/comm contains 'runit-init', ps fails, service manager is runit
# should end up return 'runit'
module = self._mock_module()
module.run_command = Mock(return_value=(1, '', ''))
collected_facts = {'ansible_system': 'Linux'}
fact_collector = self.collector_class()
facts_dict = fact_collector.collect(module=module,
collected_facts=collected_facts)
self.assertIsInstance(facts_dict, dict)
self.assertEqual(facts_dict['service_mgr'], 'runit')
@patch('ansible.module_utils.facts.system.service_mgr.get_file_content', return_value=None)
@patch('ansible.module_utils.facts.system.service_mgr.os.path.islink', side_effect=lambda x: x == '/sbin/init')
@patch('ansible.module_utils.facts.system.service_mgr.os.readlink', side_effect=lambda x: '/sbin/runit-init' if x == '/sbin/init' else '/bin/false')
def test_service_mgr_runit_no_comm(self, mock_gfc, mock_opl, mock_orl):
# no /proc/1/comm, ps returns 'COMMAND\n', service manager is runit
# should end up return 'runit'
module = self._mock_module()
module.run_command = Mock(return_value=(1, 'COMMAND\n', ''))
collected_facts = {'ansible_system': 'Linux'}
fact_collector = self.collector_class()
facts_dict = fact_collector.collect(module=module,
collected_facts=collected_facts)
self.assertIsInstance(facts_dict, dict)
self.assertEqual(facts_dict['service_mgr'], 'runit')
# TODO: reenable these tests when we can mock more easily
# @patch('ansible.module_utils.facts.system.service_mgr.get_file_content', return_value=None)