mirror of
https://github.com/cmehay/pyentrypoint
synced 2024-10-30 15:21:11 +00:00
Add globbing match to reloader config
This commit is contained in:
parent
aca34177e5
commit
88e5a66507
@ -125,6 +125,7 @@ reload:
|
|||||||
watch_config_files: true # Optional, watch defined config files, default True
|
watch_config_files: true # Optional, watch defined config files, default True
|
||||||
files: # Optional, list of files to watch
|
files: # Optional, list of files to watch
|
||||||
- /etc/conf/to/watch
|
- /etc/conf/to/watch
|
||||||
|
- /file/support/*.matching
|
||||||
# can also be enabled like this:
|
# can also be enabled like this:
|
||||||
reload: true
|
reload: true
|
||||||
|
|
||||||
|
@ -236,6 +236,7 @@ Accept boolean or dictionary
|
|||||||
watch_config_files: true # Optional, watch defined config files, default True
|
watch_config_files: true # Optional, watch defined config files, default True
|
||||||
files: # Optional, list of files to watch
|
files: # Optional, list of files to watch
|
||||||
- /etc/conf/to/watch
|
- /etc/conf/to/watch
|
||||||
|
- /file/support/*.matching
|
||||||
# can also be enabled with a boolean:
|
# can also be enabled with a boolean:
|
||||||
reload: true
|
reload: true
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import glob
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
from multiprocessing import Process
|
from multiprocessing import Process
|
||||||
@ -18,14 +19,14 @@ class Reload(FileSystemEventHandler):
|
|||||||
|
|
||||||
"""Reload object"""
|
"""Reload object"""
|
||||||
|
|
||||||
def __init__(self, sig, files, pid=1):
|
def __init__(self, sig, reloader, pid=1):
|
||||||
self.signal = sig
|
self.signal = sig
|
||||||
self.files = files
|
self.reloader = reloader
|
||||||
self.pid = pid
|
self.pid = pid
|
||||||
self.log = Logs().log
|
self.log = Logs().log
|
||||||
|
|
||||||
def on_any_event(self, event):
|
def on_any_event(self, event):
|
||||||
if event.src_path in self.files:
|
if event.src_path in self.reloader.files:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
'File {file} has changed, send sig {sig} to pid {pid}'.format(
|
'File {file} has changed, send sig {sig} to pid {pid}'.format(
|
||||||
file=event.src_path,
|
file=event.src_path,
|
||||||
@ -34,6 +35,12 @@ class Reload(FileSystemEventHandler):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
os.kill(self.pid, self.signal)
|
os.kill(self.pid, self.signal)
|
||||||
|
else:
|
||||||
|
self.log.debug(
|
||||||
|
'Reloader triggered but file {file} not watched'.format(
|
||||||
|
file=file
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Reloader(object):
|
class Reloader(object):
|
||||||
@ -44,6 +51,7 @@ class Reloader(object):
|
|||||||
if not files:
|
if not files:
|
||||||
raise Exception('No file to watch for reload')
|
raise Exception('No file to watch for reload')
|
||||||
|
|
||||||
|
self.log = Logs().log
|
||||||
self.proc = None
|
self.proc = None
|
||||||
self._files = files
|
self._files = files
|
||||||
sig_attr = getattr(signal, sig)
|
sig_attr = getattr(signal, sig)
|
||||||
@ -52,13 +60,18 @@ class Reloader(object):
|
|||||||
except:
|
except:
|
||||||
raise Exception('Wrong signal provided for reload')
|
raise Exception('Wrong signal provided for reload')
|
||||||
self.observer = Observer()
|
self.observer = Observer()
|
||||||
rel = Reload(sig=sig_attr, files=self.files)
|
rel = Reload(sig=sig_attr, reloader=self)
|
||||||
for dir in self.dirs:
|
for dir in self.dirs:
|
||||||
|
self.log.debug('Registering watcher for {dir}'.format(dir=dir))
|
||||||
self.observer.schedule(rel, dir, recursive=False)
|
self.observer.schedule(rel, dir, recursive=False)
|
||||||
|
|
||||||
def _get_files(self):
|
def _get_files(self):
|
||||||
"""Return iterator of tuples (path, file)"""
|
"""Return iterator of tuples (path, file)"""
|
||||||
for f in self._files:
|
for f in self._files:
|
||||||
|
for m in glob.iglob(f):
|
||||||
|
if os.path.isdir(m):
|
||||||
|
yield (m, m)
|
||||||
|
yield (os.path.dirname(m), m)
|
||||||
if os.path.isdir(f):
|
if os.path.isdir(f):
|
||||||
yield (f, f)
|
yield (f, f)
|
||||||
yield (os.path.dirname(f), f)
|
yield (os.path.dirname(f), f)
|
||||||
|
2
setup.py
2
setup.py
@ -5,7 +5,7 @@ from setuptools import setup
|
|||||||
|
|
||||||
# Thanks Sam and Max
|
# Thanks Sam and Max
|
||||||
|
|
||||||
__version__ = '0.4.3'
|
__version__ = '0.4.4'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
setup(
|
setup(
|
||||||
|
@ -4,7 +4,8 @@ config_files:
|
|||||||
reload:
|
reload:
|
||||||
watch_config_files: false
|
watch_config_files: false
|
||||||
files:
|
files:
|
||||||
- /tmp/reload_custom
|
- /tmp/1/reload_custom
|
||||||
|
- /tmp/2/*.match
|
||||||
|
|
||||||
pre_conf_commands:
|
pre_conf_commands:
|
||||||
- touch /tmp/reload_custom
|
- touch /tmp/reload_custom
|
||||||
|
@ -21,18 +21,23 @@ from signal import SIGHUP
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
|
||||||
|
def _reloader_check(conf, command):
|
||||||
|
entry = Entrypoint(conf=conf)
|
||||||
|
entry.apply_conf()
|
||||||
|
entry.config.reload.run(ret=True)
|
||||||
|
subprocess.check_call(command)
|
||||||
|
sleep(1)
|
||||||
|
entry.config.reload.stop()
|
||||||
|
|
||||||
|
|
||||||
def test_reloader():
|
def test_reloader():
|
||||||
|
|
||||||
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
|
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
|
||||||
os.environ.pop('ENTRYPOINT_DISABLE_RELOAD')
|
os.environ.pop('ENTRYPOINT_DISABLE_RELOAD')
|
||||||
|
|
||||||
with mock.patch('os.kill') as os_kill:
|
with mock.patch('os.kill') as os_kill:
|
||||||
entry = Entrypoint(conf='configs/reloader/reloader.yml')
|
_reloader_check(conf='configs/reloader/reloader.yml',
|
||||||
entry.apply_conf()
|
command=['touch', '/tmp/reload'])
|
||||||
entry.config.reload.run(ret=True)
|
|
||||||
subprocess.check_call(['touch', '/tmp/reload'])
|
|
||||||
sleep(1)
|
|
||||||
entry.config.reload.stop()
|
|
||||||
os_kill.assert_called_once_with(1, SIGHUP)
|
os_kill.assert_called_once_with(1, SIGHUP)
|
||||||
|
|
||||||
|
|
||||||
@ -52,12 +57,21 @@ def test_reloader_custom():
|
|||||||
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
|
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
|
||||||
os.environ.pop('ENTRYPOINT_DISABLE_RELOAD')
|
os.environ.pop('ENTRYPOINT_DISABLE_RELOAD')
|
||||||
|
|
||||||
|
subprocess.check_call(['mkdir', '-p', '/tmp/1', '/tmp/2'])
|
||||||
|
subprocess.check_call(['touch', '/tmp/2/tmp.match'])
|
||||||
|
|
||||||
with mock.patch('os.kill') as os_kill:
|
with mock.patch('os.kill') as os_kill:
|
||||||
entry = Entrypoint(conf='configs/reloader/reloader_config.yml')
|
_reloader_check(conf='configs/reloader/reloader_config.yml',
|
||||||
entry.apply_conf()
|
command=['touch', '/tmp/1/reload_custom'])
|
||||||
entry.run_pre_conf_cmds()
|
# triggered twice because file creation
|
||||||
entry.config.reload.run(ret=True)
|
os_kill.assert_called_with(1, SIGHUP)
|
||||||
subprocess.check_call(['touch', '/tmp/reload', '/tmp/reload_custom'])
|
|
||||||
sleep(1)
|
with mock.patch('os.kill') as os_kill:
|
||||||
entry.config.reload.stop()
|
_reloader_check(conf='configs/reloader/reloader_config.yml',
|
||||||
|
command=['touch', '/tmp/2/tmp.match'])
|
||||||
os_kill.assert_called_once_with(1, SIGHUP)
|
os_kill.assert_called_once_with(1, SIGHUP)
|
||||||
|
|
||||||
|
with mock.patch('os.kill') as os_kill:
|
||||||
|
_reloader_check(conf='configs/reloader/reloader_config.yml',
|
||||||
|
command=['touch', '/tmp/2/tmpnotmatch'])
|
||||||
|
assert not os_kill.called
|
||||||
|
Loading…
Reference in New Issue
Block a user