1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

launchd: Handle deprecated APIs in plistlib (#1554)

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Abhijeet Kasurde 2020-12-30 11:25:32 +05:30 committed by GitHub
parent 620dd7e8da
commit 6c88b69d6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 7 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- launchd - handle deprecated APIs like ``readPlist`` and ``writePlist`` in ``plistlib`` (https://github.com/ansible-collections/community.general/issues/1552).

View file

@ -114,6 +114,7 @@ from abc import ABCMeta, abstractmethod
from time import sleep
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
class ServiceState:
@ -142,6 +143,9 @@ class Plist:
state, pid, dummy, dummy = LaunchCtlList(module, service).run()
# Check if readPlist is available or not
self.old_plistlib = hasattr(plistlib, 'readPlist')
self.__file = self.__find_service_plist(service)
if self.__file is None:
msg = 'Unable to infer the path of %s service plist file' % service
@ -150,7 +154,8 @@ class Plist:
module.fail_json(msg=msg)
self.__update(module)
def __find_service_plist(self, service_name):
@staticmethod
def __find_service_plist(service_name):
"""Finds the plist file associated with a service"""
launchd_paths = [
@ -176,9 +181,38 @@ class Plist:
self.__handle_param_enabled(module)
self.__handle_param_force_stop(module)
def __read_plist_file(self, module):
service_plist = {}
if self.old_plistlib:
return plistlib.readPlist(self.__file)
# readPlist is deprecated in Python 3 and onwards
try:
with open(self.__file, 'rb') as plist_fp:
service_plist = plistlib.load(plist_fp)
except Exception as e:
module.fail_json(msg="Failed to read plist file "
"%s due to %s" % (self.__file, to_native(e)))
return service_plist
def __write_plist_file(self, module, service_plist=None):
if not service_plist:
service_plist = {}
if self.old_plistlib:
plistlib.writePlist(service_plist, self.__file)
return
# writePlist is deprecated in Python 3 and onwards
try:
with open(self.__file, 'wb') as plist_fp:
plistlib.dump(service_plist, plist_fp)
except Exception as e:
module.fail_json(msg="Failed to write to plist file "
" %s due to %s" % (self.__file, to_native(e)))
def __handle_param_enabled(self, module):
if module.params['enabled'] is not None:
service_plist = plistlib.readPlist(self.__file)
service_plist = self.__read_plist_file(module)
# Enable/disable service startup at boot if requested
# Launchctl does not expose functionality to set the RunAtLoad
@ -191,12 +225,12 @@ class Plist:
# Update the plist with one of the changes done.
if not module.check_mode:
plistlib.writePlist(service_plist, self.__file)
self.__write_plist_file(module, service_plist)
self.__changed = True
def __handle_param_force_stop(self, module):
if module.params['force_stop'] is not None:
service_plist = plistlib.readPlist(self.__file)
service_plist = self.__read_plist_file(module)
# Set KeepAlive to false in case force_stop is defined to avoid
# that the service gets restarted when stopping was requested.
@ -207,7 +241,7 @@ class Plist:
# Update the plist with one of the changes done.
if not module.check_mode:
plistlib.writePlist(service_plist, self.__file)
self.__write_plist_file(module, service_plist)
self.__changed = True
def is_changed(self):
@ -325,7 +359,7 @@ class LaunchCtlStart(LaunchCtlTask):
def runCommand(self):
state, dummy, dummy, dummy = self.get_state()
if state == ServiceState.STOPPED or state == ServiceState.LOADED:
if state in (ServiceState.STOPPED, ServiceState.LOADED):
self.reload()
self.start()
elif state == ServiceState.STARTED:
@ -361,7 +395,7 @@ class LaunchCtlStop(LaunchCtlTask):
if self._plist.is_changed():
self.reload()
self.stop()
elif state == ServiceState.STARTED or state == ServiceState.LOADED:
elif state in (ServiceState.STARTED, ServiceState.LOADED):
if self._plist.is_changed():
self.reload()
self.stop()