blueprint change: worker indexing functionregister (#1065)
* blueprint change: worker indexing functionregister * fix flakey8 * temp update to 3b2 * update unit tests * fix functionregister err msg Co-authored-by: peterstone2017 <yunchuwang5@gmail.com> Co-authored-by: Varad Meru <vrdmr@users.noreply.github.com>
This commit is contained in:
Родитель
f51a1f1b0f
Коммит
1b52d72d8b
|
@ -143,18 +143,19 @@ def index_function_app(function_path: str):
|
||||||
module_name = pathlib.Path(function_path).stem
|
module_name = pathlib.Path(function_path).stem
|
||||||
imported_module = importlib.import_module(module_name)
|
imported_module = importlib.import_module(module_name)
|
||||||
|
|
||||||
from azure.functions import FunctionApp
|
from azure.functions import FunctionRegister
|
||||||
app: Optional[FunctionApp] = None
|
app: Optional[FunctionRegister] = None
|
||||||
for i in imported_module.__dir__():
|
for i in imported_module.__dir__():
|
||||||
if isinstance(getattr(imported_module, i, None), FunctionApp):
|
if isinstance(getattr(imported_module, i, None), FunctionRegister):
|
||||||
if not app:
|
if not app:
|
||||||
app = getattr(imported_module, i, None)
|
app = getattr(imported_module, i, None)
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Multiple instances of FunctionApp are defined")
|
f"More than one {app.__class__.__name__} or other top "
|
||||||
|
f"level function app instances are defined.")
|
||||||
|
|
||||||
if not app:
|
if not app:
|
||||||
raise ValueError("Could not find instance of FunctionApp in "
|
raise ValueError("Could not find top level function app instances in "
|
||||||
f"{SCRIPT_FILE_NAME}.")
|
f"{SCRIPT_FILE_NAME}.")
|
||||||
|
|
||||||
return app.get_functions()
|
return app.get_functions()
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -105,7 +105,7 @@ INSTALL_REQUIRES = [
|
||||||
"grpcio~=1.43.0",
|
"grpcio~=1.43.0",
|
||||||
"grpcio-tools~=1.43.0",
|
"grpcio-tools~=1.43.0",
|
||||||
"protobuf~=3.19.3",
|
"protobuf~=3.19.3",
|
||||||
'azure-functions==1.11.3b2',
|
"azure-functions==1.11.3b2",
|
||||||
"python-dateutil~=2.8.2"
|
"python-dateutil~=2.8.2"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import azure.functions as func
|
||||||
|
|
||||||
|
bp = func.Blueprint()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(route="default_template")
|
||||||
|
def default_template(req: func.HttpRequest) -> func.HttpResponse:
|
||||||
|
logging.info('Python HTTP trigger function processed a request.')
|
||||||
|
|
||||||
|
name = req.params.get('name')
|
||||||
|
if not name:
|
||||||
|
try:
|
||||||
|
req_body = req.get_json()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
name = req_body.get('name')
|
||||||
|
|
||||||
|
if name:
|
||||||
|
return func.HttpResponse(
|
||||||
|
f"Hello, {name}. This HTTP triggered function "
|
||||||
|
f"executed successfully.")
|
||||||
|
else:
|
||||||
|
return func.HttpResponse(
|
||||||
|
"This HTTP triggered function executed successfully. "
|
||||||
|
"Pass a name in the query string or in the request body for a"
|
||||||
|
" personalized response.",
|
||||||
|
status_code=200
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
import azure.functions as func
|
||||||
|
from blueprint import bp
|
||||||
|
|
||||||
|
app = func.FunctionApp()
|
||||||
|
|
||||||
|
app.register_functions(bp)
|
|
@ -0,0 +1,31 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import azure.functions as func
|
||||||
|
|
||||||
|
bp = func.Blueprint()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(route="default_template")
|
||||||
|
def default_template(req: func.HttpRequest) -> func.HttpResponse:
|
||||||
|
logging.info('Python HTTP trigger function processed a request.')
|
||||||
|
|
||||||
|
name = req.params.get('name')
|
||||||
|
if not name:
|
||||||
|
try:
|
||||||
|
req_body = req.get_json()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
name = req_body.get('name')
|
||||||
|
|
||||||
|
if name:
|
||||||
|
return func.HttpResponse(
|
||||||
|
f"Hello, {name}. This HTTP triggered function "
|
||||||
|
f"executed successfully.")
|
||||||
|
else:
|
||||||
|
return func.HttpResponse(
|
||||||
|
"This HTTP triggered function executed successfully. "
|
||||||
|
"Pass a name in the query string or in the request body for a"
|
||||||
|
" personalized response.",
|
||||||
|
status_code=200
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
import azure.functions as func
|
||||||
|
|
||||||
|
from blueprint import bp
|
||||||
|
|
||||||
|
app = func.FunctionApp()
|
||||||
|
|
||||||
|
app.register_blueprint(bp)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(route="return_http")
|
||||||
|
def return_http(req: func.HttpRequest):
|
||||||
|
return func.HttpResponse('<h1>Hello World™</h1>',
|
||||||
|
mimetype='text/html')
|
|
@ -0,0 +1,12 @@
|
||||||
|
import azure.functions as func
|
||||||
|
|
||||||
|
app = func.FunctionApp()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(route="return_http")
|
||||||
|
def return_http(req: func.HttpRequest):
|
||||||
|
return func.HttpResponse('<h1>Hello World™</h1>',
|
||||||
|
mimetype='text/html')
|
||||||
|
|
||||||
|
|
||||||
|
asgi_app = func.AsgiFunctionApp()
|
|
@ -0,0 +1,31 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import azure.functions as func
|
||||||
|
|
||||||
|
bp = func.Blueprint()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(route="default_template")
|
||||||
|
def default_template(req: func.HttpRequest) -> func.HttpResponse:
|
||||||
|
logging.info('Python HTTP trigger function processed a request.')
|
||||||
|
|
||||||
|
name = req.params.get('name')
|
||||||
|
if not name:
|
||||||
|
try:
|
||||||
|
req_body = req.get_json()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
name = req_body.get('name')
|
||||||
|
|
||||||
|
if name:
|
||||||
|
return func.HttpResponse(
|
||||||
|
f"Hello, {name}. This HTTP triggered function "
|
||||||
|
f"executed successfully.")
|
||||||
|
else:
|
||||||
|
return func.HttpResponse(
|
||||||
|
"This HTTP triggered function executed successfully. "
|
||||||
|
"Pass a name in the query string or in the request body for a"
|
||||||
|
" personalized response.",
|
||||||
|
status_code=200
|
||||||
|
)
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
# Licensed under the MIT License.
|
||||||
|
|
||||||
|
from azure_functions_worker import testutils
|
||||||
|
|
||||||
|
|
||||||
|
class TestFunctionInBluePrintOnly(testutils.WebHostTestCase):
|
||||||
|
@classmethod
|
||||||
|
def get_script_dir(cls):
|
||||||
|
return testutils.E2E_TESTS_FOLDER / 'blueprint_functions' / \
|
||||||
|
'functions_in_blueprint_only'
|
||||||
|
|
||||||
|
@testutils.retryable_test(3, 5)
|
||||||
|
def test_function_in_blueprint_only(self):
|
||||||
|
r = self.webhost.request('GET', 'default_template')
|
||||||
|
self.assertTrue(r.ok)
|
||||||
|
|
||||||
|
|
||||||
|
class TestFunctionsInBothBlueprintAndFuncApp(testutils.WebHostTestCase):
|
||||||
|
@classmethod
|
||||||
|
def get_script_dir(cls):
|
||||||
|
return testutils.E2E_TESTS_FOLDER / 'blueprint_functions' / \
|
||||||
|
'functions_in_both_blueprint_functionapp'
|
||||||
|
|
||||||
|
@testutils.retryable_test(3, 5)
|
||||||
|
def test_functions_in_both_blueprint_functionapp(self):
|
||||||
|
r = self.webhost.request('GET', 'default_template')
|
||||||
|
self.assertTrue(r.ok)
|
||||||
|
|
||||||
|
r = self.webhost.request('GET', 'return_http')
|
||||||
|
self.assertTrue(r.ok)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMultipleFunctionRegisters(testutils.WebHostTestCase):
|
||||||
|
@classmethod
|
||||||
|
def get_script_dir(cls):
|
||||||
|
return testutils.E2E_TESTS_FOLDER / 'blueprint_functions' / \
|
||||||
|
'multiple_function_registers'
|
||||||
|
|
||||||
|
@testutils.retryable_test(3, 5)
|
||||||
|
def test_function_in_blueprint_only(self):
|
||||||
|
r = self.webhost.request('GET', 'return_http')
|
||||||
|
self.assertEqual(r.status_code, 404)
|
||||||
|
|
||||||
|
|
||||||
|
class TestOnlyBlueprint(testutils.WebHostTestCase):
|
||||||
|
@classmethod
|
||||||
|
def get_script_dir(cls):
|
||||||
|
return testutils.E2E_TESTS_FOLDER / 'blueprint_functions' / \
|
||||||
|
'only_blueprint'
|
||||||
|
|
||||||
|
@testutils.retryable_test(3, 5)
|
||||||
|
def test_only_blueprint(self):
|
||||||
|
"""Test if the default template of Http trigger in Python
|
||||||
|
Function app
|
||||||
|
will return OK
|
||||||
|
"""
|
||||||
|
r = self.webhost.request('GET', 'default_template')
|
||||||
|
self.assertEqual(r.status_code, 404)
|
|
@ -37,5 +37,5 @@ async def raise_http_exception():
|
||||||
raise HTTPException(status_code=404, detail="Item not found")
|
raise HTTPException(status_code=404, detail="Item not found")
|
||||||
|
|
||||||
|
|
||||||
app = func.FunctionApp(asgi_app=fast_app,
|
app = func.AsgiFunctionApp(app=fast_app,
|
||||||
http_auth_level=func.AuthLevel.ANONYMOUS)
|
http_auth_level=func.AuthLevel.ANONYMOUS)
|
||||||
|
|
|
@ -32,5 +32,5 @@ def raise_http_exception():
|
||||||
return {"detail": "Item not found"}, 404
|
return {"detail": "Item not found"}, 404
|
||||||
|
|
||||||
|
|
||||||
app = func.FunctionApp(wsgi_app=flask_app.wsgi_app,
|
app = func.WsgiFunctionApp(app=flask_app.wsgi_app,
|
||||||
http_auth_level=func.AuthLevel.ANONYMOUS)
|
http_auth_level=func.AuthLevel.ANONYMOUS)
|
||||||
|
|
|
@ -172,5 +172,5 @@ async def unhandled_unserializable_error():
|
||||||
raise UnserializableException('foo')
|
raise UnserializableException('foo')
|
||||||
|
|
||||||
|
|
||||||
app = func.FunctionApp(asgi_app=fast_app,
|
app = func.AsgiFunctionApp(app=fast_app,
|
||||||
http_auth_level=func.AuthLevel.ANONYMOUS)
|
http_auth_level=func.AuthLevel.ANONYMOUS)
|
||||||
|
|
|
@ -99,5 +99,5 @@ def unhandled_unserializable_error():
|
||||||
raise UnserializableException('foo')
|
raise UnserializableException('foo')
|
||||||
|
|
||||||
|
|
||||||
app = func.FunctionApp(wsgi_app=flask_app.wsgi_app,
|
app = func.WsgiFunctionApp(app=flask_app.wsgi_app,
|
||||||
http_auth_level=func.AuthLevel.ANONYMOUS)
|
http_auth_level=func.AuthLevel.ANONYMOUS)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче