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

Add set_environment in settings

```yaml
set_environment:
    - ENV_1: echo 'The environment variable ENV_1 will be added with this phrase'
    - ENV_2: head /dev/urandom | base64
    - ENV_3: echo ${ENV_1} and ${ENV_2} are now available here
    - ENV_4: exit 1 || true  # Set like this if you need to ignore error
```
This commit is contained in:
Christophe Mehay 2020-05-30 18:49:13 +02:00
parent 50540203b1
commit f1882dab3c
10 changed files with 76 additions and 12 deletions

View File

@ -1,3 +1,6 @@
v0.7.2
- add set_environment in settings
v0.7.1 v0.7.1
- add envtobool function in configuration template - add envtobool function in configuration template

View File

@ -14,6 +14,9 @@ This tool avoids writing shell scripts to:
## Changelog ## Changelog
###### v0.7.2 (2020-05-30)
- add set_environment in settings
###### v0.7.1 (2020-05-24) ###### v0.7.1 (2020-05-24)
- add envtobool function in configuration template - add envtobool function in configuration template
@ -161,6 +164,15 @@ links:
# true by default # true by default
required: true required: true
# Set custom environment variable by running commands
# Will run before pre_conf_commands and capture stdout only
# Stop init if crash
set_environment:
- ENV_1: echo 'The environment variable ENV_1 will be added with this phrase'
- ENV_2: head /dev/urandom | base64
- ENV_3: echo ${ENV_1} and ${ENV_2} are now available here
- ENV_4: exit 1 || true # Set like this if you need to ignore error
# Commands to run before applying configuration # Commands to run before applying configuration
pre_conf_commands: pre_conf_commands:
- echo something > to_this_file - echo something > to_this_file

View File

@ -74,7 +74,16 @@ This is an example of ``entrypoint-config.yml`` file.
single: true single: true
# Set to false to get optional link # Set to false to get optional link
# true by default # true by default
required: true required: true
# Set custom environment variable by running commands
# Will run before pre_conf_commands and capture stdout only
# Stop init if crash
set_environment:
- ENV_1: echo 'The environment variable ENV_1 will be added with this phrase'
- ENV_2: head /dev/urandom | base64
- ENV_3: echo ${ENV_1} and ${ENV_2} are now available here
- ENV_4: exit 1 || true # Add this if you need to ignore error
# Commands to run before applying configuration # Commands to run before applying configuration
pre_conf_commands: pre_conf_commands:

View File

@ -233,6 +233,12 @@ class Config(ConfigMeta):
else: else:
return ['-*'] return ['-*']
@property
def set_environment(self):
"""Set environment variables at runtime"""
return self._get_by_command(item='set_environment',
value_types=[list, dict])
@property @property
def user(self): def user(self):
"Unix user or uid to run command." "Unix user or uid to run command."

View File

@ -30,7 +30,7 @@ class Entrypoint(object):
def __init__(self, conf=ENTRYPOINT_FILE, args=[]): def __init__(self, conf=ENTRYPOINT_FILE, args=[]):
self._set_logguer() self._set_logguer()
if 'ENTRYPOINT_CONFIG' in os.environ: if os.environ.get('ENTRYPOINT_CONFIG'):
conf = os.environ['ENTRYPOINT_CONFIG'] conf = os.environ['ENTRYPOINT_CONFIG']
try: try:
self.config = Config(conf=conf, args=args) self.config = Config(conf=conf, args=args)
@ -91,16 +91,25 @@ class Entrypoint(object):
envtobool=envtobool, envtobool=envtobool,
containers=DockerLinks().to_containers())) containers=DockerLinks().to_containers()))
def run_set_enviroment(self):
for set_env in self.config.set_environment:
if not isinstance(set_env, dict) and not len(set_env) == 1:
raise Exception("set_environment is miss configured, "
"please check syntax in entrypoint config")
env, cmd = next(((e, c) for e, c in set_env.items()))
self.log.debug(f'Set environment variable {env}')
os.environ[env] = self.runner.run_cmd(cmd, stdout=True)
def run_pre_conf_cmds(self): def run_pre_conf_cmds(self):
for cmd in self.config.pre_conf_commands: for cmd in self.config.pre_conf_commands:
self.runner.run_cmd(cmd) self.runner.run_cmd(cmd)
if 'ENTRYPOINT_PRECONF_COMMAND' in os.environ: if os.environ.get('ENTRYPOINT_PRECONF_COMMAND'):
self.runner.run_cmd(os.environ['ENTRYPOINT_PRECONF_COMMAND']) self.runner.run_cmd(os.environ['ENTRYPOINT_PRECONF_COMMAND'])
def run_post_conf_cmds(self): def run_post_conf_cmds(self):
for cmd in self.config.post_conf_commands: for cmd in self.config.post_conf_commands:
self.runner.run_cmd(cmd) self.runner.run_cmd(cmd)
if 'ENTRYPOINT_POSTCONF_COMMAND' in os.environ: if os.environ.get('ENTRYPOINT_POSTCONF_COMMAND'):
self.runner.run_cmd(os.environ['ENTRYPOINT_POSTCONF_COMMAND']) self.runner.run_cmd(os.environ['ENTRYPOINT_POSTCONF_COMMAND'])
def launch(self): def launch(self):
@ -117,6 +126,7 @@ def main(argv):
entry.launch() entry.launch()
entry.config.set_to_env() entry.config.set_to_env()
entry.log.debug("Starting config") entry.log.debug("Starting config")
entry.run_set_enviroment()
entry.run_pre_conf_cmds() entry.run_pre_conf_cmds()
entry.apply_conf() entry.apply_conf()
entry.run_post_conf_cmds() entry.run_post_conf_cmds()

View File

@ -2,7 +2,7 @@
from multiprocessing import Process from multiprocessing import Process
from subprocess import PIPE from subprocess import PIPE
from subprocess import Popen from subprocess import Popen
from sys import stdout from sys import stdout as stdoutput
from .logs import Logs from .logs import Logs
@ -15,13 +15,13 @@ class Runner(object):
self.cmds = cmds self.cmds = cmds
self.raw_output = config.raw_output self.raw_output = config.raw_output
def run_cmd(self, cmd): def run_cmd(self, cmd, stdout=False):
self.log.debug('run command: {}'.format(cmd)) self.log.debug('run command: {}'.format(cmd))
proc = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) proc = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate() out, err = proc.communicate()
def dispout(output, cb): def dispout(output, cb):
enc = stdout.encoding or 'UTF-8' enc = stdoutput.encoding or 'UTF-8'
output = output.decode(enc).split('\n') output = output.decode(enc).split('\n')
lenght = len(output) lenght = len(output)
for c, line in enumerate(output): for c, line in enumerate(output):
@ -30,12 +30,14 @@ class Runner(object):
break break
cb(line) cb(line)
if out:
display_cb = self.log.info if not self.raw_output else print
dispout(out, display_cb)
if err: if err:
display_cb = self.log.warning if not self.raw_output else print display_cb = self.log.warning if not self.raw_output else print
dispout(err, display_cb) dispout(err, display_cb)
if out:
display_cb = self.log.info if not self.raw_output else print
if stdout:
return out.decode()
dispout(out, display_cb)
if proc.returncode: if proc.returncode:
raise Exception('Command exit code: {}'.format(proc.returncode)) raise Exception('Command exit code: {}'.format(proc.returncode))

View File

@ -27,6 +27,7 @@ pre_conf_commands:
- echo TEST > /tmp/OK - echo TEST > /tmp/OK
- echo "INFO IS DISPLAYED" - echo "INFO IS DISPLAYED"
- echo "WARNING IS DISPLAYED\nON TWO LINES" 1>&2 - echo "WARNING IS DISPLAYED\nON TWO LINES" 1>&2
- echo ${ENV_1} > /tmp_env_1
post_conf_commands: post_conf_commands:
- echo TEST2 > /tmp/OKOK - echo TEST2 > /tmp/OKOK
@ -36,5 +37,10 @@ post_conf_commands:
- echo ${ENTRYPOINT_DEBUG} > /tmp/debug - echo ${ENTRYPOINT_DEBUG} > /tmp/debug
- echo "INFO IS DISPLAYED\nON TWO LINES" - echo "INFO IS DISPLAYED\nON TWO LINES"
- echo "WARNING IS DISPLAYED" 1>&2 - echo "WARNING IS DISPLAYED" 1>&2
- echo ${ENV_2} > /tmp_env_2
set_environment:
- ENV_1: echo ENV_1 set
- ENV_2: echo ENV_2 set
debug: true debug: true

View File

@ -49,6 +49,12 @@ post_run_commands:
- zsh: - zsh:
- cmd9 - cmd9
set_environment:
- bash:
- ENV_1: echo set ENV_1
- zsh:
- ENV_2: echo set ENV_2
debug: debug:
- zsh: false - zsh: false
- '*sh': true - '*sh': true

View File

@ -171,12 +171,15 @@ def test_conf_commands():
('/tmp/user', '1000'), ('/tmp/user', '1000'),
('/tmp/group', '1000'), ('/tmp/group', '1000'),
('/tmp/debug', 'true'), ('/tmp/debug', 'true'),
('/tmp_env_1', 'ENV_1 set'),
('/tmp_env_2', 'ENV_2 set')
] ]
os.environ['ENTRYPOINT_PRECONF_COMMAND'] = 'echo TEST4 > /tmp/OKOKOKOK' os.environ['ENTRYPOINT_PRECONF_COMMAND'] = 'echo TEST4 > /tmp/OKOKOKOK'
os.environ['ENTRYPOINT_POSTCONF_COMMAND'] = 'echo TEST5 > /tmp/OKOKOKOKOK' os.environ['ENTRYPOINT_POSTCONF_COMMAND'] = 'echo TEST5 > /tmp/OKOKOKOKOK'
entry.config.set_to_env() entry.config.set_to_env()
entry.run_set_enviroment()
entry.run_pre_conf_cmds() entry.run_pre_conf_cmds()
entry.run_post_conf_cmds() entry.run_post_conf_cmds()
@ -380,6 +383,13 @@ def test_command_matching_setup():
'cmd5', 'cmd5',
] ]
assert bash.config.set_environment == [
{'ENV_1': 'echo set ENV_1'}
]
assert zsh.config.set_environment == [
{'ENV_2': 'echo set ENV_2'}
]
assert bash.config.post_run_commands == [ assert bash.config.post_run_commands == [
'cmd7', 'cmd7',
'cmd8', 'cmd8',

View File

@ -36,7 +36,7 @@ def _reloader_check(conf, command):
def test_reloader(): def test_reloader():
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ: if os.environ.get('ENTRYPOINT_DISABLE_RELOAD'):
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:
@ -58,7 +58,7 @@ def test_disabled_reloader():
def test_reloader_custom(): def test_reloader_custom():
if 'ENTRYPOINT_DISABLE_RELOAD' in os.environ: if os.environ.get('ENTRYPOINT_DISABLE_RELOAD'):
os.environ.pop('ENTRYPOINT_DISABLE_RELOAD') os.environ.pop('ENTRYPOINT_DISABLE_RELOAD')
subprocess.check_call(['mkdir', '-p', '/tmp/1', '/tmp/2']) subprocess.check_call(['mkdir', '-p', '/tmp/1', '/tmp/2'])