Skip to content

Commit

Permalink
bugy#181 added mapping script parameters to env variables
Browse files Browse the repository at this point in the history
  • Loading branch information
bugy authored and antonellocaroli committed Aug 1, 2020
1 parent 35d0b93 commit ad418f2
Show file tree
Hide file tree
Showing 18 changed files with 501 additions and 22 deletions.
3 changes: 2 additions & 1 deletion samples/configs/parameterized.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"name": "Required Text",
"required": true,
"param": "--required_text",
"description": "Parameter One"
"description": "Parameter One",
"env_var": "Req_Text"
},
{
"name": "Required List",
Expand Down
5 changes: 5 additions & 0 deletions samples/scripts/parameterized.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ else
echo "--file_upload: "`md5sum "$my_file"`
fi

echo
echo 'Environment variables:'
echo 'Req_Text='"$Req_Text"
printenv | grep -P '^PARAM_'

sleep 5
59 changes: 54 additions & 5 deletions src/execution/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

from execution import process_popen, process_base
from model import model_helper
from model.model_helper import read_bool
from utils import file_utils, process_utils, os_utils
from utils.transliteration import transliterate

TIME_BUFFER_MS = 100

Expand All @@ -13,7 +15,7 @@
mock_process = False


def create_process_wrapper(executor, command, working_directory):
def create_process_wrapper(executor, command, working_directory, env_variables):
run_pty = executor.config.requires_terminal
if run_pty and not os_utils.is_pty_supported():
LOGGER.warning(
Expand All @@ -22,9 +24,9 @@ def create_process_wrapper(executor, command, working_directory):

if run_pty:
from execution import process_pty
process_wrapper = process_pty.PtyProcessWrapper(command, working_directory)
process_wrapper = process_pty.PtyProcessWrapper(command, working_directory, env_variables)
else:
process_wrapper = process_popen.POpenProcessWrapper(command, working_directory)
process_wrapper = process_popen.POpenProcessWrapper(command, working_directory, env_variables)

return process_wrapper

Expand Down Expand Up @@ -86,10 +88,13 @@ def start(self):
if self.process_wrapper is not None:
raise Exception('Executor already started')

script_args = build_command_args(self.get_script_parameter_values(), self.config)
parameter_values = self.get_script_parameter_values()

script_args = build_command_args(parameter_values, self.config)
command = self.script_base_command + script_args
env_variables = _build_env_variables(parameter_values, self.config.parameters)

process_wrapper = _process_creator(self, command, self._working_directory)
process_wrapper = _process_creator(self, command, self._working_directory, env_variables)
process_wrapper.start()

self.process_wrapper = process_wrapper
Expand Down Expand Up @@ -225,6 +230,50 @@ def build_command_args(param_values, config):
return result


def _to_env_name(key):
transliterated = transliterate(key)
replaced = re.sub('[^0-9a-zA-Z_]+', '_', transliterated)
if replaced == '_':
return None

return 'PARAM_' + replaced.upper()


def _build_env_variables(parameter_values, parameters):
result = {}
excluded = []
for param_name, value in parameter_values.items():
if isinstance(value, list) or (value is None):
continue

found_parameters = [p for p in parameters if p.name == param_name]
if len(found_parameters) != 1:
continue

parameter = found_parameters[0]

env_var = parameter.env_var
if env_var is None:
env_var = _to_env_name(param_name)

if (not env_var) or (env_var in excluded):
continue

if env_var in result:
excluded.append(env_var)
del result[env_var]
continue

if parameter.no_value:
if (value is not None) and (read_bool(value) == True):
result[env_var] = 'true'
continue

result[env_var] = str(value)

return result


def _concat_output(output_chunks):
if not output_chunks:
return output_chunks
Expand Down
3 changes: 2 additions & 1 deletion src/execution/process_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
LOGGER = logging.getLogger('script_server.process_base')

class ProcessWrapper(metaclass=abc.ABCMeta):
def __init__(self, command, working_directory):
def __init__(self, command, working_directory, env_variables):
self.process = None

self.working_directory = working_directory
self.command = command
self.env_variables = env_variables

self.finish_listeners = []

Expand Down
9 changes: 6 additions & 3 deletions src/execution/process_popen.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

LOGGER = logging.getLogger('script_server.process_popen')


def prepare_cmd_for_win(command):
shell = False

Expand All @@ -22,23 +23,25 @@ def prepare_cmd_for_win(command):


class POpenProcessWrapper(process_base.ProcessWrapper):
def __init__(self, command, working_directory):
super().__init__(command, working_directory)
def __init__(self, command, working_directory, env_variables):
super().__init__(command, working_directory, env_variables)

def start_execution(self, command, working_directory):
shell = False

if os_utils.is_win():
(command, shell) = prepare_cmd_for_win(command)

env_variables = dict(os.environ, **self.env_variables)
self.process = subprocess.Popen(command,
cwd=working_directory,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
start_new_session=True,
universal_newlines=True,
shell=shell)
shell=shell,
env=env_variables)

def write_to_input(self, value):
input_value = value
Expand Down
10 changes: 7 additions & 3 deletions src/execution/process_pty.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def _unset_output_flags(fd, *new_attributes):


class PtyProcessWrapper(process_base.ProcessWrapper):
def __init__(self, command, working_directory):
super().__init__(command, working_directory)
def __init__(self, command, working_directory, env_variables):
super().__init__(command, working_directory, env_variables)

self.pty_master = None
self.pty_slave = None
Expand All @@ -36,12 +36,16 @@ def __init__(self, command, working_directory):

def start_execution(self, command, working_directory):
master, slave = pty.openpty()

env_variables = dict(os.environ, **self.env_variables)

self.process = subprocess.Popen(command,
cwd=working_directory,
stdin=slave,
stdout=slave,
stderr=slave,
start_new_session=True)
start_new_session=True,
env=env_variables)
self.pty_slave = slave
self.pty_master = master

Expand Down
2 changes: 2 additions & 0 deletions src/model/parameter_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

@observable_fields(
'param',
'env_var',
'no_value',
'description',
'required',
Expand Down Expand Up @@ -61,6 +62,7 @@ def _reload(self):
config = self._original_config

self.param = config.get('param')
self.env_var = config.get('env_var')
self.no_value = read_bool_from_config('no_value', config, default=False)
self.description = config.get('description')
self.required = read_bool_from_config('required', config, default=False)
Expand Down
2 changes: 1 addition & 1 deletion src/tests/execution/process_pty_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def test_many_unicode_characters(self):
long_unicode_text = ('ΩΨΔ\n' * 100000)
test_utils.create_file('test.txt', text=long_unicode_text)

process_wrapper = PtyProcessWrapper(['cat', 'test.txt'], test_utils.temp_folder)
process_wrapper = PtyProcessWrapper(['cat', 'test.txt'], test_utils.temp_folder, {})
process_wrapper.start()

thread = threading.Thread(target=process_wrapper.wait_finish, daemon=True)
Expand Down
4 changes: 2 additions & 2 deletions src/tests/execution_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ def setUp(self):
self.exec_services = []
self.processes = {}

def create_process(executor, command, working_directory):
wrapper = _MockProcessWrapper(executor, command, working_directory)
def create_process(executor, command, working_directory, env_variables):
wrapper = _MockProcessWrapper(executor, command, working_directory, env_variables)
self.processes[self.get_last_id()] = wrapper
return wrapper

Expand Down
Loading

0 comments on commit ad418f2

Please sign in to comment.