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

Respawn modules to use the system python interpreter #460

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions changelogs/fragments/460-respawn.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
minor_changes:
- "seboolean - respawn module to use the system python interpreter when the ``selinux`` python module is not available for ``ansible_python_interpreter``
(https://github.com/ansible-collections/ansible.posix/pull/460)."
- "selinux - respawn module to use the system python interpreter when the ``selinux`` python module is not available for ``ansible_python_interpreter``
(https://github.com/ansible-collections/ansible.posix/pull/460)."
- "firewalld - respawn module to use the system python interpreter when the ``firewall`` python module is not available for ``ansible_python_interpreter``
(https://github.com/ansible-collections/ansible.posix/pull/460)."
- "firewalld_info - respawn module to use the system python interpreter when the ``firewall`` python module is not available for ``ansible_python_interpreter``
(https://github.com/ansible-collections/ansible.posix/pull/460)."
45 changes: 45 additions & 0 deletions plugins/module_utils/_respawn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (c) 2023 Maxwell G <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

"""
Helpers to respawn a module to run using the system interpreter
"""

from __future__ import absolute_import, division, print_function

__metaclass__ = type

try:
from ansible.module_utils.common import respawn
except ImportError:
HAS_RESPAWN_UTIL = False
else:
HAS_RESPAWN_UTIL = True


SYSTEM_PYTHON_INTERPRETERS = (
"/usr/bin/libexec/platform-python",
"/usr/bin/python3",
"/usr/bin/python2",
"/usr/bin/python",
)


def respawn_module(module):
"""
Respawn an ansible module to using the first interpreter in
SYSTEM_PYTHON_INTERPRETERS that contains `module`.

Args:
module (str): Name of python module to search for

Returns:
Returns None if the module cannot be respawned.
"""
if respawn.has_respawned():
return
interpreter = respawn.probe_interpreters_for_module(
SYSTEM_PYTHON_INTERPRETERS, module
)
if interpreter:
respawn.respawn_module(interpreter)
3 changes: 3 additions & 0 deletions plugins/module_utils/firewalld.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from __future__ import absolute_import, division, print_function
from ansible_collections.ansible.posix.plugins.module_utils.version import LooseVersion
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
from ansible.module_utils.basic import missing_required_lib

__metaclass__ = type
Expand Down Expand Up @@ -314,6 +315,8 @@ def sanity_check(module):
installed version (%s) likely too old. Requires firewalld >= 0.2.11" % FW_VERSION)

if import_failure:
if HAS_RESPAWN_UTIL:
respawn_module("firewall")
module.fail_json(
msg=missing_required_lib('firewall') + '. Version 0.2.11 or newer required (0.3.9 or newer for offline operations)'
)
7 changes: 7 additions & 0 deletions plugins/modules/firewalld_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@

from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils._text import to_native
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion


Expand Down Expand Up @@ -322,6 +323,12 @@ def main():
)

# Exit with failure message if requirements modules are not installed.
if not HAS_DBUS and not HAS_FIREWALLD and HAS_RESPAWN_UTIL:
# Only respawn the module if both libraries are missing.
# If only one is available, then usage of the "wrong" (i.e. not the system one)
# python interpreter is likely not the problem.
respawn_module("firewall")

if not HAS_DBUS:
module.fail_json(msg=missing_required_lib('python-dbus'))
if not HAS_FIREWALLD:
Expand Down
7 changes: 7 additions & 0 deletions plugins/modules/seboolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.six import binary_type
from ansible.module_utils._text import to_bytes, to_text
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL


def get_runtime_status(ignore_selinux_state=False):
Expand Down Expand Up @@ -281,6 +282,12 @@ def main():
supports_check_mode=True,
)

if not HAVE_SELINUX and not HAVE_SEMANAGE and HAS_RESPAWN_UTIL:
# Only respawn the module if both libraries are missing.
# If only one is available, then usage of the "wrong" (i.e. not the system one)
# python interpreter is likely not the problem.
respawn_module("selinux")

if not HAVE_SELINUX:
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)

Expand Down
4 changes: 4 additions & 0 deletions plugins/modules/selinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.facts.utils import get_file_lines

from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL


# getter subroutines
def get_config_state(configfile):
Expand Down Expand Up @@ -236,6 +238,8 @@ def main():
)

if not HAS_SELINUX:
if HAS_RESPAWN_UTIL:
respawn_module("selinux")
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)

# global vars
Expand Down
7 changes: 0 additions & 7 deletions tests/integration/targets/firewalld/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
state: present
# This doesn't work for CentOS 6 because firewalld doesn't exist in CentOS6

- name: Check to make sure the firewalld python module is available.
shell: "{{ansible_python.executable}} -c 'import firewall'"
register: check_output
ignore_errors: true

- name: Enable dbus-broker daemon
service:
name: dbus-broker
Expand All @@ -30,7 +25,6 @@
state: started

- import_tasks: run_all_tests.yml
when: check_output.rc == 0

- name: Test Offline Operations
block:
Expand All @@ -40,7 +34,6 @@
state: stopped

- import_tasks: run_all_tests.yml
when: check_output.rc == 0

when:
- ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version('7', '>=')
Expand Down
Loading