Skip to content

Commit f10fddc

Browse files
committed
move function app to individual blueprint
Signed-off-by: MD Ashique <noorani.ashique5@gmail.com>
1 parent ad0f900 commit f10fddc

13 files changed

+149
-137
lines changed

samples/python-azurefunction/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Python Azure Function Sample
22

3-
This tutorial will demonstrate how to use Azure Functions Python programming model to integrate with multiple Dapr components. Please first go through the [samples](https://github.com/dapr/samples) to get some contexts on various Dapr building blocks as well as go through Azure Functions [hello-world sample](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code?pivots=programming-language-python) to familiarize with function programming model.
3+
This tutorial will demonstrate how to use Azure Functions Python programming model to integrate with multiple Dapr components. Please first go through the [samples](https://github.com/dapr/samples) to get some contexts on various Dapr building blocks as well as go through Azure Functions [hello-world sample](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code?pivots=programming-language-python) to familiarize with function programming model. [Please explore Functions Dapr extension with Python V2 programming model samples for simplified development](https://github.com/Azure/azure-functions-dapr-extension/tree/master/samples/python-v2-azurefunctions).
4+
45
We'll be running a Darp'd function app locally:
56
1) Invoked by [Dapr Service Invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/service-invocation-overview/) and persist/retrieve state using [Dapr State Management](https://github.com/dapr/components-contrib/tree/master/state)
67
2) Publish/consume message on a specific topic powered by [Dapr pub/sub](https://github.com/dapr/components-contrib/tree/master/pubsub) and `DaprPublish`/`DaprTopicTrigger`

samples/python-v2-azurefunctions/.funcignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

samples/python-v2-azurefunctions/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ spec:
5252
....
5353
```
5454

55+
# DaprBlueprint
56+
The Python v2 programming model introduces the concept of blueprints. A blueprint is a new class that's instantiated to register functions outside of the core function application. The functions registered in blueprint instances aren't indexed directly by the function runtime. To get these blueprint functions indexed, the function app needs to register the functions from blueprint instances.
57+
58+
## Using blueprints provides the following benefits:
59+
60+
- Lets you break up the function app into modular components, which enables you to define functions in multiple Python files and divide them into different components per file.
61+
- Provides extensible public function app interfaces to build and reuse your own APIs.
62+
5563
# Step 2 - Run Function App with Dapr
5664

5765
Build the function app:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import logging
2+
import azure.functions as func
3+
4+
consumeMessageFromKafka = func.DaprBlueprint()
5+
6+
# Dapr binding trigger
7+
@consumeMessageFromKafka.function_name(name="ConsumeMessageFromKafka")
8+
@consumeMessageFromKafka.dapr_binding_trigger(arg_name="triggerData", binding_name="%KafkaBindingName%")
9+
def main(triggerData: str) -> None:
10+
logging.info('Python function processed a ConsumeMessageFromKafka request from the Dapr Runtime.')
11+
logging.info('Trigger data: ' + triggerData)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import logging
2+
import azure.functions as func
3+
4+
createNewOrder = func.DaprBlueprint()
5+
6+
# Dapr state output binding with http dapr_service_invocation_trigger
7+
@createNewOrder.function_name(name="CreateNewOrder")
8+
@createNewOrder.dapr_service_invocation_trigger(arg_name="payload", method_name="CreateNewOrder")
9+
@createNewOrder.dapr_state_output(arg_name="state", state_store="%StateStoreName%", key="order")
10+
def main(payload: str, state: func.Out[str] ) :
11+
# request body must be passed this way '{\"value\": { \"key\": \"some value\" } }'
12+
logging.info('Python function processed a CreateNewOrder request from the Dapr Runtime.')
13+
logging.info(payload)
14+
if payload is not None:
15+
state.set(payload)
16+
else:
17+
logging.info('payload is none')

samples/python-v2-azurefunctions/dapr_blueprint_app.py

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 17 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,20 @@
1-
# import logging
2-
# import json
3-
# import azure.functions as func
4-
5-
6-
# def main(payload,
7-
# order: func.Out[str]) -> None:
8-
# logging.info(
9-
# 'Python function processed a CreateNewOrder request from the Dapr Runtime.')
10-
# payload_json = json.loads(payload)
11-
# logging.info(payload_json["data"])
12-
# order.set(json.dumps({"value": payload_json["data"]}))
13-
14-
15-
import json
161
import azure.functions as func
17-
import logging
18-
import json
19-
import azure.functions as func
20-
import logging
21-
from dapr_blueprint_app import app
22-
23-
dapp = func.DaprFunctionApp()
24-
dapp.register_blueprint(app)
25-
26-
# Dapr state output binding with http trigger
27-
@dapp.function_name(name="HttpTriggerFunc")
28-
@dapp.route(route="req", auth_level=dapp.auth_level.ANONYMOUS)
29-
@dapp.dapr_state_output(arg_name="state", state_store="statestore", key="newOrder")
30-
def main(req: func.HttpRequest, state: func.Out[str] ) -> str:
31-
# request body must be passed this way '{\"value\": { \"key\": \"some value\" } }'
32-
body = req.get_body()
33-
logging.info(body.decode('utf-8'))
34-
if body is not None:
35-
state.set(body.decode('utf-8'))
36-
logging.info(body.decode('utf-8'))
37-
else:
38-
logging.info('req body is none')
39-
return 'ok'
402

41-
# Dapr state output binding with http dapr_service_invocation_trigger
42-
@dapp.function_name(name="CreateNewOrder")
43-
@dapp.dapr_service_invocation_trigger(arg_name="payload", method_name="CreateNewOrder")
44-
@dapp.dapr_state_output(arg_name="state", state_store="statestore", key="order")
45-
def main(payload: str, state: func.Out[str] ) :
46-
# request body must be passed this way '{\"value\": { \"key\": \"some value\" } }'
47-
logging.info('Python function processed a CreateNewOrder request from the Dapr Runtime.')
48-
logging.info(payload)
49-
if payload is not None:
50-
state.set(payload)
51-
else:
52-
logging.info('payload is none')
3+
from create_new_order import createNewOrder
4+
from consume_message_from_kafka import consumeMessageFromKafka
5+
from invoke_output_binding import invokeOutputBinding
6+
from print_topic_message import printTopicMessage
7+
from retrieve_order import retrieveOrder
8+
from retrieve_secret import retrieveSecret
9+
from send_message_to_kafka import sendMessageToKafka
10+
from transfer_event_between_topics import transferEventBetweenTopics
5311

54-
# Dapr state input binding with http dapr_service_invocation_trigger
55-
@dapp.function_name(name="RetrieveOrder")
56-
@dapp.dapr_service_invocation_trigger(arg_name="payload", method_name="RetrieveOrder")
57-
@dapp.dapr_state_input(arg_name="data", state_store="statestore", key="order")
58-
def main(payload, data: str) :
59-
# Function should be invoked with this command: dapr invoke --app-id functionapp --method RetrieveOrder --data '{}'
60-
logging.info('Python function processed a RetrieveOrder request from the Dapr Runtime.')
61-
logging.info(data)
62-
63-
# Dapr secret input binding with http dapr_service_invocation_trigger
64-
@dapp.function_name(name="RetrieveSecret")
65-
@dapp.dapr_service_invocation_trigger(arg_name="payload", method_name="RetrieveSecret")
66-
@dapp.dapr_secret_input(arg_name="secret", secret_store_name="localsecretstore", key="my-secret", metadata="metadata.namespace=default")
67-
def main(payload, secret: str) :
68-
# Function should be invoked with this command: dapr invoke --app-id functionapp --method RetrieveSecret --data '{}'
69-
logging.info('Python function processed a RetrieveSecret request from the Dapr Runtime.')
70-
secret_dict = json.loads(secret)
71-
72-
for key in secret_dict:
73-
logging.info("Stored secret: Key = " + key +
74-
', Value = ' + secret_dict[key])
75-
76-
# Dapr binding output
77-
# Dapr state output binding with http dapr_service_invocation_trigger
78-
@dapp.function_name(name="SendMessageToKafka")
79-
@dapp.dapr_service_invocation_trigger(arg_name="payload", method_name="SendMessageToKafka")
80-
@dapp.dapr_binding_output(arg_name="messages", binding_name="%KafkaBindingName%", operation="create")
81-
def main(payload: str, messages: func.Out[bytes]) -> None:
82-
logging.info('Python processed a SendMessageToKafka request from the Dapr Runtime.')
83-
messages.set(json.dumps({"data": payload}).encode('utf-8'))
84-
85-
# Dapr binding trigger
86-
@dapp.function_name(name="ConsumeMessageFromKafka")
87-
@dapp.dapr_binding_trigger(arg_name="triggerData", binding_name="%KafkaBindingName%")
88-
def main(triggerData: str) -> None:
89-
logging.info('Python function processed a ConsumeMessageFromKafka request from the Dapr Runtime.')
90-
logging.info('Trigger data: ' + triggerData)
91-
92-
# Dapr topic trigger
93-
@dapp.function_name(name="PrintTopicMessage")
94-
@dapp.dapr_topic_trigger(arg_name="subEvent", pub_sub_name="%PubSubName%", topic="B", route="B")
95-
def main(subEvent) -> None:
96-
logging.info('Python function processed a PrintTopicMessage request from the Dapr Runtime.')
97-
subEvent_json = json.loads(subEvent)
98-
logging.info("Topic B received a message: " + subEvent_json["data"])
99-
100-
# Dapr publish output
101-
# Dapr topic trigger with dapr_publish_output
102-
@dapp.function_name(name="TransferEventBetweenTopics")
103-
@dapp.dapr_topic_trigger(arg_name="subEvent", pub_sub_name="%PubSubName%", topic="A", route="A")
104-
@dapp.dapr_publish_output(arg_name="pubEvent", pub_sub_name="%PubSubName%", topic="B")
105-
def main(subEvent, pubEvent: func.Out[bytes]) -> None:
106-
logging.info('Python function processed a TransferEventBetweenTopics request from the Dapr Runtime.')
107-
subEvent_json = json.loads(subEvent)
108-
payload = "Transfer from Topic A: " + str(subEvent_json["data"])
109-
pubEvent.set(json.dumps({"payload": payload}).encode('utf-8'))
110-
111-
# Dapr invoke output binding with http trigger
112-
@dapp.function_name(name="InvokeOutputBinding")
113-
@dapp.route(route="invoke/{appId}/{methodName}", auth_level=dapp.auth_level.ANONYMOUS)
114-
@dapp.dapr_invoke_output(arg_name = "payload", app_id = "{appId}", method_name = "{methodName}", http_verb = "post")
115-
def main(req: func.HttpRequest, payload: func.Out[str] ) -> str:
116-
# request body must be passed this way "{\"body\":{\"value\":{\"key\":\"some value\"}}}" to use the InvokeOutputBinding, all the data must be enclosed in body property.
117-
logging.info('Python function processed a InvokeOutputBinding request from the Dapr Runtime.')
118-
119-
body = req.get_body()
120-
logging.info(body)
121-
if body is not None:
122-
payload.set(body)
123-
else:
124-
logging.info('req body is none')
125-
return 'ok'
12+
dapp = func.DaprFunctionApp()
13+
dapp.register_blueprint(createNewOrder)
14+
dapp.register_blueprint(consumeMessageFromKafka)
15+
dapp.register_blueprint(invokeOutputBinding)
16+
dapp.register_blueprint(printTopicMessage)
17+
dapp.register_blueprint(retrieveOrder)
18+
dapp.register_blueprint(retrieveSecret)
19+
dapp.register_blueprint(sendMessageToKafka)
20+
dapp.register_blueprint(transferEventBetweenTopics)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import logging
2+
import azure.functions as func
3+
4+
invokeOutputBinding = func.DaprBlueprint()
5+
6+
# Dapr invoke output binding with http trigger
7+
@invokeOutputBinding.function_name(name="InvokeOutputBinding")
8+
@invokeOutputBinding.route(route="invoke/{appId}/{methodName}", auth_level=func.AuthLevel.ANONYMOUS)
9+
@invokeOutputBinding.dapr_invoke_output(arg_name = "payload", app_id = "{appId}", method_name = "{methodName}", http_verb = "post")
10+
def main(req: func.HttpRequest, payload: func.Out[str] ) -> str:
11+
# request body must be passed this way "{\"body\":{\"value\":{\"key\":\"some value\"}}}" to use the InvokeOutputBinding, all the data must be enclosed in body property.
12+
logging.info('Python function processed a InvokeOutputBinding request from the Dapr Runtime.')
13+
14+
body = req.get_body()
15+
logging.info(body)
16+
if body is not None:
17+
payload.set(body)
18+
else:
19+
logging.info('req body is none')
20+
return 'ok'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import json
2+
import logging
3+
import azure.functions as func
4+
5+
printTopicMessage = func.DaprBlueprint()
6+
7+
# Dapr topic trigger
8+
@printTopicMessage.function_name(name="PrintTopicMessage")
9+
@printTopicMessage.dapr_topic_trigger(arg_name="subEvent", pub_sub_name="%PubSubName%", topic="B", route="B")
10+
def main(subEvent) -> None:
11+
logging.info('Python function processed a PrintTopicMessage request from the Dapr Runtime.')
12+
subEvent_json = json.loads(subEvent)
13+
logging.info("Topic B received a message: " + subEvent_json["data"])
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import logging
2+
import azure.functions as func
3+
4+
retrieveOrder = func.DaprBlueprint()
5+
6+
# Dapr state input binding with http dapr_service_invocation_trigger
7+
@retrieveOrder.function_name(name="RetrieveOrder")
8+
@retrieveOrder.dapr_service_invocation_trigger(arg_name="payload", method_name="RetrieveOrder")
9+
@retrieveOrder.dapr_state_input(arg_name="data", state_store="%StateStoreName%", key="order")
10+
def main(payload, data: str) :
11+
# Function should be invoked with this command: dapr invoke --app-id functionapp --method RetrieveOrder --data '{}'
12+
logging.info('Python function processed a RetrieveOrder request from the Dapr Runtime.')
13+
logging.info(data)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import json
2+
import logging
3+
import azure.functions as func
4+
5+
retrieveSecret = func.DaprBlueprint()
6+
7+
# Dapr secret input binding with http dapr_service_invocation_trigger
8+
@retrieveSecret.function_name(name="RetrieveSecret")
9+
@retrieveSecret.dapr_service_invocation_trigger(arg_name="payload", method_name="RetrieveSecret")
10+
@retrieveSecret.dapr_secret_input(arg_name="secret", secret_store_name="localsecretstore", key="my-secret", metadata="metadata.namespace=default")
11+
def main(payload, secret: str) :
12+
# Function should be invoked with this command: dapr invoke --app-id functionapp --method RetrieveSecret --data '{}'
13+
logging.info('Python function processed a RetrieveSecret request from the Dapr Runtime.')
14+
secret_dict = json.loads(secret)
15+
16+
for key in secret_dict:
17+
logging.info("Stored secret: Key = " + key +
18+
', Value = ' + secret_dict[key])
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import json
2+
import logging
3+
import azure.functions as func
4+
5+
sendMessageToKafka = func.DaprBlueprint()
6+
7+
# Dapr binding output
8+
# Dapr state output binding with http dapr_service_invocation_trigger
9+
@sendMessageToKafka.function_name(name="SendMessageToKafka")
10+
@sendMessageToKafka.dapr_service_invocation_trigger(arg_name="payload", method_name="SendMessageToKafka")
11+
@sendMessageToKafka.dapr_binding_output(arg_name="messages", binding_name="%KafkaBindingName%", operation="create")
12+
def main(payload: str, messages: func.Out[bytes]) -> None:
13+
logging.info('Python processed a SendMessageToKafka request from the Dapr Runtime.')
14+
messages.set(json.dumps({"data": payload}).encode('utf-8'))
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import json
2+
import logging
3+
import azure.functions as func
4+
5+
transferEventBetweenTopics = func.DaprBlueprint()
6+
7+
# Dapr publish output
8+
# Dapr topic trigger with dapr_publish_output
9+
@transferEventBetweenTopics.function_name(name="TransferEventBetweenTopics")
10+
@transferEventBetweenTopics.dapr_topic_trigger(arg_name="subEvent", pub_sub_name="%PubSubName%", topic="A", route="A")
11+
@transferEventBetweenTopics.dapr_publish_output(arg_name="pubEvent", pub_sub_name="%PubSubName%", topic="B")
12+
def main(subEvent, pubEvent: func.Out[bytes]) -> None:
13+
logging.info('Python function processed a TransferEventBetweenTopics request from the Dapr Runtime.')
14+
subEvent_json = json.loads(subEvent)
15+
payload = "Transfer from Topic A: " + str(subEvent_json["data"])
16+
pubEvent.set(json.dumps({"payload": payload}).encode('utf-8'))

0 commit comments

Comments
 (0)