Skip to content

Commit

Permalink
Update environment reload logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanzhang Zeng (Roger) committed Jan 30, 2020
1 parent 3869532 commit 7541899
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 4 deletions.
14 changes: 14 additions & 0 deletions azure_functions_worker/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ async def _handle__function_environment_reload_request(self, req):
logger.info('Unable to reload azure.functions. '
'Using default. Exception:\n{}'.format(ex))

# Change function app directory
if getattr(func_env_reload_request, 'function_app_directory'):
self._change_current_working_directory(
func_env_reload_request.function_app_directory)

success_response = protos.FunctionEnvironmentReloadResponse(
result=protos.StatusResult(
status=protos.StatusResult.Success))
Expand All @@ -426,6 +431,15 @@ async def _handle__function_environment_reload_request(self, req):
request_id=self.request_id,
function_environment_reload_response=failure_response)

def _change_current_working_directory(self, new_working_directory: str):
if os.path.exists(new_working_directory):
os.chdir(new_working_directory)
logger.info('Changing current working directory to %s',
new_working_directory)
else:
logger.warn('Working directory %s is not found when reload',
new_working_directory)

def __run_sync_func(self, invocation_id, func, params):
# This helper exists because we need to access the current
# invocation_id from ThreadPoolExecutor's threads.
Expand Down
15 changes: 15 additions & 0 deletions tests/unittests/load_functions/parentmodule/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"scriptFile": "sub_module/main.py",
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
1 change: 1 addition & 0 deletions tests/unittests/load_functions/parentmodule/module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MODULE_NAME = 'PARENTMODULE'
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .. import module


def main(req) -> str:
return module.__name__
15 changes: 15 additions & 0 deletions tests/unittests/load_functions/submodule/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"scriptFile": "main.py",
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
5 changes: 5 additions & 0 deletions tests/unittests/load_functions/submodule/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .sub_module import module


def main(req) -> str:
return module.__name__
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MODULE_NAME = 'SUB_MODULE'
10 changes: 10 additions & 0 deletions tests/unittests/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ def test_loader_relimport(self):
self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, '__app__.relimport.relative')

def test_loader_submodule(self):
r = self.webhost.request('GET', 'submodule')
self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, '__app__.submodule.sub_module.module')

def test_loader_parentmodule(self):
r = self.webhost.request('GET', 'parentmodule')
self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, '__app__.parentmodule.module')


class TestPluginLoader(testutils.AsyncTestCase):

Expand Down
26 changes: 22 additions & 4 deletions tests/unittests/test_rpc_messages.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import os
import subprocess
import sys
import typing
import tempfile

from azure_functions_worker import protos
from azure_functions_worker import testutils


class TestGRPC(testutils.AsyncTestCase):
pre_test_env = os.environ.copy()
pre_test_cwd = os.getcwd()

def _reset_environ(self):
for key, value in self.pre_test_env.items():
os.environ[key] = value
os.chdir(self.pre_test_cwd)

async def _verify_environment_reloaded(self, test_env):
async def _verify_environment_reloaded(
self,
test_env: typing.Dict[str, str] = {},
test_cwd: str = os.getcwd()):
request = protos.FunctionEnvironmentReloadRequest(
environment_variables=test_env)
environment_variables=test_env,
function_app_directory=test_cwd)

request_msg = protos.StreamingMessage(
request_id='0',
Expand All @@ -29,18 +37,28 @@ async def _verify_environment_reloaded(self, test_env):

environ_dict = os.environ.copy()
self.assertDictEqual(environ_dict, test_env)
self.assertEqual(os.getcwd(), test_cwd)
status = r.function_environment_reload_response.result.status
self.assertEqual(status, protos.StatusResult.Success)
finally:
self._reset_environ()

async def test_multiple_env_vars_load(self):
test_env = {'TEST_KEY': 'foo', 'HELLO': 'world'}
await self._verify_environment_reloaded(test_env)
await self._verify_environment_reloaded(test_env=test_env)

async def test_empty_env_vars_load(self):
test_env = {}
await self._verify_environment_reloaded(test_env)
await self._verify_environment_reloaded(test_env=test_env)

async def test_changing_current_working_directory(self):
test_cwd = tempfile.gettempdir()
await self._verify_environment_reloaded(test_cwd=test_cwd)

async def test_reload_env_message(self):
test_env = {'TEST_KEY': 'foo', 'HELLO': 'world'}
test_cwd = tempfile.gettempdir()
await self._verify_environment_reloaded(test_env, test_cwd)

def _verify_sys_path_import(self, result, expected_output):
try:
Expand Down

0 comments on commit 7541899

Please sign in to comment.