2
0
mirror of https://github.com/cmehay/pyentrypoint synced 2024-10-30 15:21:11 +00:00

Fix setgid, add env to disable reloader

This commit is contained in:
Christophe Mehay 2016-11-19 17:19:10 +01:00
parent 10d80a705c
commit c935e22252
10 changed files with 97 additions and 15 deletions

View File

@ -4,6 +4,9 @@ FROM python:2
RUN pip install pytest six pyyaml jinja2 colorlog watchdog pytest-mock RUN pip install pytest six pyyaml jinja2 colorlog watchdog pytest-mock
RUN adduser --uid 1009 --system testuser
RUN addgroup --gid 1010 testgroup
ENV PYTHONPATH /opt/ ENV PYTHONPATH /opt/
ADD tests/test_template.yml.tpl /tmp/test_template.yml ADD tests/test_template.yml.tpl /tmp/test_template.yml

View File

@ -4,6 +4,9 @@ FROM python:3
RUN pip3 install pytest six pyyaml jinja2 colorlog watchdog pytest-mock RUN pip3 install pytest six pyyaml jinja2 colorlog watchdog pytest-mock
RUN adduser --uid 1009 --system testuser
RUN addgroup --gid 1010 testgroup
ENV PYTHONPATH /opt/ ENV PYTHONPATH /opt/
ADD tests/test_template.yml.tpl /tmp/test_template.yml ADD tests/test_template.yml.tpl /tmp/test_template.yml

View File

@ -7,6 +7,7 @@ This tool avoids writing shell scripts to:
- Identify linked containers - Identify linked containers
- Generate configuration using `jinja2` templates - Generate configuration using `jinja2` templates
- Run commands before starting service - Run commands before starting service
- Reload service when configuration has changed
[![Documentation Status](https://readthedocs.org/projects/pyentrypoint/badge/?version=latest)](http://pyentrypoint.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/pyentrypoint/badge/?version=latest)](http://pyentrypoint.readthedocs.io/en/latest/?badge=latest)
@ -247,6 +248,11 @@ Some setups can be overridden using environment variables.
- `ENTRYPOINT_DEBUG` enables debug logs. - `ENTRYPOINT_DEBUG` enables debug logs.
- `ENTRYPOINT_RAW` does not use logging to display pre and post conf commands. - `ENTRYPOINT_RAW` does not use logging to display pre and post conf commands.
This can be useful if output is serialized. This can be useful if output is serialized.
- `ENTRYPOINT_DISABLE_RELOAD` disable reload system even if it is enabled in `entrypoint-config.yml`.
- `ENTRYPOINT_USER` overrides `user` in config.
- `ENTRYPOINT_GROUP` overrides `group` in config.
### Running Tests ### Running Tests

View File

@ -7,10 +7,14 @@ Some setups can be overridden using environment variables in the container.
file. file.
- ``ENTRYPOINT_FORCE`` applies configuration and runs pre and post conf - ``ENTRYPOINT_FORCE`` applies configuration and runs pre and post conf
commands even if the ``command`` provided is not handled. commands even if the ``command`` provided is not handled.
- ``ENTRYPOINT_PRECONF_COMMAND`` run an extra pre conf shell command after - ``ENTRYPOINT_PRECONF_COMMAND`` run an extra pre conf shell command after
all pre conf commands. all pre conf commands.
- ``ENTRYPOINT_POSTCONF_COMMAND`` run an extra post conf shell command after - ``ENTRYPOINT_POSTCONF_COMMAND`` run an extra post conf shell command after
all post conf commands. all post conf commands.
- ``ENTRYPOINT_DEBUG`` enables debug logs. - ``ENTRYPOINT_DEBUG`` enables debug logs.
- ``ENTRYPOINT_RAW`` does not use logging to display pre and post conf commands. - ``ENTRYPOINT_RAW`` does not use logging to display pre and post conf
This can be useful if output is serialized. commands. This can be useful if output is serialized.
- ``ENTRYPOINT_DISABLE_RELOAD`` disable reload system even if it is enabled
in ``entrypoint-config.yml``.
- ``ENTRYPOINT_USER`` overrides ``user`` in config.
- ``ENTRYPOINT_GROUP`` overrides ``group`` in config.

View File

@ -71,6 +71,16 @@ class ConfigMeta(object):
'"{key}" is not a valid option'.format(key=key) '"{key}" is not a valid option'.format(key=key)
) )
def _get_from_env(self, env, key):
val = os.environ.get(env, None)
if val is None:
return None
try:
val = int(val)
except ValueError:
pass
self._config[key] = val
class Config(ConfigMeta): class Config(ConfigMeta):
@ -125,6 +135,7 @@ class Config(ConfigMeta):
@property @property
def user(self): def user(self):
"Unix user or uid to run command." "Unix user or uid to run command."
self._get_from_env(env='ENTRYPOINT_USER', key='user')
if 'user' in self._config: if 'user' in self._config:
if isinstance(self._config['user'], int): if isinstance(self._config['user'], int):
return self._config['user'] return self._config['user']
@ -134,10 +145,11 @@ class Config(ConfigMeta):
@property @property
def group(self): def group(self):
"Unix group or gid to run command." "Unix group or gid to run command."
self._get_from_env(env='ENTRYPOINT_GROUP', key='group')
if 'group' in self._config: if 'group' in self._config:
if isinstance(self._config['user'], int): if isinstance(self._config['group'], int):
return self._config['user'] return self._config['group']
return getgrnam(self._config['user']).gr_gid return getgrnam(self._config['group']).gr_gid
return os.getgid() return os.getgid()
@property @property
@ -176,9 +188,11 @@ class Config(ConfigMeta):
@property @property
def reload(self): def reload(self):
"""Return Reloader object if reload is set""" """Return Reloader object if reload is set"""
if self._reload: if self._reload:
return self._reload return self._reload
if not self._config.get('reload'): if (not self._config.get('reload') or
'ENTRYPOINT_DISABLE_RELOAD' in os.environ):
return None return None
self._reload = self.get_reloader() self._reload = self.get_reloader()
return self._reload return self._reload

View File

@ -5,7 +5,7 @@ from setuptools import setup
# Thanks Sam and Max # Thanks Sam and Max
__version__ = '0.4.0' __version__ = '0.4.1'
if __name__ == '__main__': if __name__ == '__main__':
setup( setup(

View File

@ -1,6 +1,6 @@
command: bash command: bash
user: www-data user: testuser
group: www-data group: testgroup
debug: true debug: true

View File

@ -49,8 +49,8 @@ def test_main():
env={'ENTRYPOINT_CONFIG': 'configs/usernames.yml'} env={'ENTRYPOINT_CONFIG': 'configs/usernames.yml'}
).run), ).run),
'/tmp/CMD__8', '/tmp/CMD__8',
33, 1009,
33, 1010,
), ( ), (
Process(target=ProxyMain( Process(target=ProxyMain(
args=['pyentrypoint', 'bash', '-c', 'echo OK > /tmp/CMD__9'], args=['pyentrypoint', 'bash', '-c', 'echo OK > /tmp/CMD__9'],

View File

@ -184,7 +184,7 @@ def test_command():
(Process(target=Entrypoint( (Process(target=Entrypoint(
conf='configs/usernames.yml', conf='configs/usernames.yml',
args=['bash', '-c', 'echo OK > /tmp/CMD3']).launch), args=['bash', '-c', 'echo OK > /tmp/CMD3']).launch),
'/tmp/CMD3', 33, 33), '/tmp/CMD3', 1009, 1010),
(Process(target=Entrypoint( (Process(target=Entrypoint(
conf='configs/unhandled.yml', conf='configs/unhandled.yml',
args=['bash', '-c', 'echo OK > /tmp/CMD4']).launch), args=['bash', '-c', 'echo OK > /tmp/CMD4']).launch),
@ -246,3 +246,36 @@ def test_debug_env():
assert entry.config.debug assert entry.config.debug
del os.environ['ENTRYPOINT_DEBUG'] del os.environ['ENTRYPOINT_DEBUG']
def test_quiet_env():
os.environ['ENTRYPOINT_QUIET'] = 'true'
entry = Entrypoint(conf='configs/empty.yml')
assert entry.config.quiet
del os.environ['ENTRYPOINT_QUIET']
def test_user_env():
os.environ['ENTRYPOINT_USER'] = '100'
entry = Entrypoint(conf='configs/base.yml')
assert entry.config.user == 100
os.environ['ENTRYPOINT_USER'] = 'testuser'
entry = Entrypoint(conf='configs/base.yml')
assert entry.config.user == 1009
def test_group_env():
os.environ['ENTRYPOINT_GROUP'] = '100'
entry = Entrypoint(conf='configs/base.yml')
assert entry.config.group == 100
os.environ['ENTRYPOINT_GROUP'] = 'testgroup'
entry = Entrypoint(conf='configs/base.yml')
assert entry.config.group == 1010

View File

@ -10,6 +10,8 @@ except ImportError:
# Python3 # Python3
from unittest import mock from unittest import mock
import os
from pyentrypoint import Entrypoint from pyentrypoint import Entrypoint
import subprocess import subprocess
@ -21,6 +23,9 @@ from time import sleep
def test_reloader(): def test_reloader():
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
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') entry = Entrypoint(conf='configs/reloader/reloader.yml')
entry.apply_conf() entry.apply_conf()
@ -31,8 +36,22 @@ def test_reloader():
os_kill.assert_called_once_with(1, SIGHUP) os_kill.assert_called_once_with(1, SIGHUP)
def test_disabled_reloader():
os.environ['ENTRYPOINT_DISABLE_RELOAD'] = 'true'
with mock.patch('os.kill') as os_kill:
entry = Entrypoint(conf='configs/reloader/reloader.yml')
entry.apply_conf()
assert entry.config.reload is None
assert not os_kill.called
def test_reloader_custom(): def test_reloader_custom():
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ:
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_config.yml') entry = Entrypoint(conf='configs/reloader/reloader_config.yml')
entry.apply_conf() entry.apply_conf()