├── License.txt
├── README.md
├── final_state_lambda
├── handle.py
└── zappa_settings.json
├── greater_than_lambda
├── handle.py
└── zappa_settings.json
├── images
├── algorithm.png
├── example.png
├── sms-rec.png
└── statemachine.png
├── less_than_lambda
├── handle.py
└── zappa_settings.json
├── requirement.txt
├── steps.json
└── sub_numbers_lambda
├── handle.py
└── zappa_settings.json
/License.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Osama
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS Step Functions
2 | "AWS Step Functions is a web service that enables you to coordinate the components of distributed applications and microservices using visual workflows. You build applications from individual components that each perform a discrete function, or task, allowing you to scale and change applications quickly."
3 |
4 | I've learned Step Functions by applying the following example and I hope it can help you in
5 |
6 | # Algorithm (Example)
7 | In this example, the algorithm takes two input numbers and subtract them,then :
8 | - If the result is larger than 100 the user should receive a SMS with a random number between 100-1000.
9 | - If it's less, then the random number in the SMS should be from 0-100.
10 | - Else it's failed scenario, with a dead end.
11 |
12 |
13 |
14 |
15 |
16 | In step functions, you can consider that each process block is an AWS Lambda Function, that takes the output of previous state as input for the current state. Therefore we have 4 Lambda functions in this example:
17 | - sub_numbers_lambda | takes { key1 : X, key2 : Y} and returns { number : Z }
18 | - greater_than_lambda | returns { final_number : rand(100,100) }
19 | - less_than_lambda | returns { final_number : rand(0,100) }
20 | - final_state_lambda | takes { final_number : C }
21 |
22 | Step functions are described with json format, where you should define :
23 | - start_state (StartAt)
24 | - final_state (End)
25 | - next_state (Next)
26 | - choise_state ( Type : Choice), which supports many comparison operators.
27 |
28 | # Step Functions Description Example
29 | ```
30 | "StartAt": "SubNumbers",
31 | "States": {
32 | "SubNumbers": {
33 | "Type": "Task",
34 | "Resource": "ARN:OF:sub-numbers",
35 | "Next": "ChoiceState"
36 | },
37 | "ChoiceState": {
38 | "Type" : "Choice",
39 | "Choices": [
40 | {
41 | "Variable": "$.number",
42 | "NumericGreaterThan": 100,
43 | "Next": "GreateThan"
44 | },
45 | {
46 | "Variable": "$.number",
47 | "NumericEquals": 100,
48 | "Next": "LessThan"
49 | }
50 | ],
51 | "Default": "EqualTo"
52 | },
53 |
54 | "GreateThan": {
55 | "Type" : "Task",
56 | "Resource": "ARN:OF:greater-than-lambda",
57 | "Next": "FinalState"
58 | },
59 |
60 | "LessThan": {
61 | "Type" : "Task",
62 | "Resource": "ARN:OF:less-than-lambda",
63 | "Next": "FinalState"
64 | },
65 |
66 | "EqualTo": {
67 | "Type": "Fail",
68 | "Cause": "No Matches!",
69 | "End": true
70 | },
71 |
72 | "FinalState": {
73 | "Type": "Task",
74 | "Resource": "ARN:OF:final-state-lambda",
75 | "End": true
76 | }
77 | }
78 | }
79 | ```
80 |
81 | # Apply it
82 | 1- Clone this repo
83 | 2- Create a python virtualenv inside it, and install pip requirements
84 | ```
85 | $ git clone git@github.com:OsamaJBR/teach-me-aws-stepfunctions.git
86 | $ cd teach-me-aws-stepfunctions
87 | $ virtualenv env
88 | $ source env/bin/activate
89 | $ pip install -r requirement.txt
90 | ```
91 | 3- Start deploying functions using [Zappa](https://github.com/Miserlou/Zappa)
92 | ```
93 | $ cd sub_numbers_lambda; zappa deploy develop
94 | $ cd greater_than_lambda; zappa deploy develop
95 | $ cd less_than_lambda; zappa deploy develop
96 | ```
97 | 4- Go to Amazon Console (AWS Lambda) page and get all ARN for the above lambda functions
98 | 5- Edit steps.json file and add ARN inside the related state definition
99 | ```
100 | ...
101 | "SubNumbers": {
102 | "Type": "Task",
103 | "Resource": "XXXXXXXXXXXX",
104 | "Next": "ChoiceState"
105 | },
106 | ...
107 | ```
108 | 6- Edit final_state_lambda by adding the SNS Topic ARN in the code, then deploy the function using zappa again
109 | ```
110 | $ cd final_state_lambda; vim handle.py
111 | ...
112 | response = client.publish(
113 | TargetArn="XXXXXXXXXXXXXXX",
114 | Message=json.dumps({'default': json.dumps(message)}),
115 | MessageStructure='json'
116 | )
117 | ...
118 | $ zappa deploy develop
119 | ```
120 | 7- Go to Amazon Step Function page, the Create State Machine. Past the edited steps.json inside the Code panel. Then you should see this in the Preview section.
121 |
122 |
123 |
124 | * If everything is ok, create it.
125 |
126 | # How to test it
127 | 1- Go to the new state machine, and press on new execution.
128 | 2- Insert the following as input, and start the execution.
129 | ```
130 | {
131 | "key1" : 100,
132 | "key2" : 300
133 | }
134 | ```
135 |
136 |
137 |
138 | 3- The final state suppose to send an SMS to the phone number subscribed in the SNS Topic.
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/final_state_lambda/handle.py:
--------------------------------------------------------------------------------
1 | import json
2 | import boto3
3 | import inflect
4 |
5 | def lambda_handler(event,context):
6 | inflect_engine = inflect.engine()
7 | number = inflect_engine.number_to_words(event['final_number'])
8 | message = {"DelMeMessage": "The StepFunctions Result is %r" %number}
9 | client = boto3.client('sns')
10 | response = client.publish(
11 | TargetArn="SNS-TOPIC-ARN",
12 | Message=json.dumps({'default': json.dumps(message)}),
13 | MessageStructure='json'
14 | )
15 |
--------------------------------------------------------------------------------
/final_state_lambda/zappa_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "develop": {
3 | "keep_warm": false,
4 | "apigateway_enabled" : false,
5 | "memory_size" : 128,
6 | "debug": false,
7 | "lambda_handler" : "handle.lambda_handler"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/greater_than_lambda/handle.py:
--------------------------------------------------------------------------------
1 | import json
2 | import random
3 |
4 | def lambda_handler(event,context):
5 | final_number = random.randint(100,1000)
6 | return {"final_number" : final_number}
--------------------------------------------------------------------------------
/greater_than_lambda/zappa_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "develop": {
3 | "keep_warm": false,
4 | "apigateway_enabled" : false,
5 | "memory_size" : 128,
6 | "debug": false ,
7 | "lambda_handler": "handle.lambda_handler"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/images/algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OsamaJBR/teach-me-aws-stepfunctions/1f3e93899d2adadffdc6469ab92d21a545eb22a1/images/algorithm.png
--------------------------------------------------------------------------------
/images/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OsamaJBR/teach-me-aws-stepfunctions/1f3e93899d2adadffdc6469ab92d21a545eb22a1/images/example.png
--------------------------------------------------------------------------------
/images/sms-rec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OsamaJBR/teach-me-aws-stepfunctions/1f3e93899d2adadffdc6469ab92d21a545eb22a1/images/sms-rec.png
--------------------------------------------------------------------------------
/images/statemachine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OsamaJBR/teach-me-aws-stepfunctions/1f3e93899d2adadffdc6469ab92d21a545eb22a1/images/statemachine.png
--------------------------------------------------------------------------------
/less_than_lambda/handle.py:
--------------------------------------------------------------------------------
1 | import json
2 | import random
3 |
4 | def lambda_handler(event,context):
5 | final_number = random.randint(0,100)
6 | return {"final_number" : final_number}
--------------------------------------------------------------------------------
/less_than_lambda/zappa_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "develop": {
3 | "keep_warm": false,
4 | "apigateway_enabled" : false,
5 | "memory_size" : 128,
6 | "debug": false,
7 | "lambda_handler": "handle.lambda_handler"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/requirement.txt:
--------------------------------------------------------------------------------
1 | boto3
2 | zappa
3 | inflect
4 |
5 |
--------------------------------------------------------------------------------
/steps.json:
--------------------------------------------------------------------------------
1 | {
2 | "Comment": "Example of ChoiceState using AWS StepFunctions",
3 | "StartAt": "SubNumbers",
4 | "States": {
5 | "SubNumbers": {
6 | "Type": "Task",
7 | "Resource": "ARN:OF:sub-numbers",
8 | "Next": "ChoiceState"
9 | },
10 | "ChoiceState": {
11 | "Type" : "Choice",
12 | "Choices": [
13 | {
14 | "Variable": "$.number",
15 | "NumericGreaterThan": 100,
16 | "Next": "GreateThan"
17 | },
18 | {
19 | "Variable": "$.number",
20 | "NumericLessThan": 100,
21 | "Next": "LessThan"
22 | }
23 | ],
24 | "Default": "EqualTo"
25 | },
26 |
27 | "GreateThan": {
28 | "Type" : "Task",
29 | "Resource": "ARN:OF:greater-than-lambda",
30 | "Next": "FinalState"
31 | },
32 |
33 | "LessThan": {
34 | "Type" : "Task",
35 | "Resource": "ARN:OF:less-than-lambda",
36 | "Next": "FinalState"
37 | },
38 |
39 | "EqualTo": {
40 | "Type": "Fail",
41 | "Cause": "No Matches!"
42 | },
43 |
44 | "FinalState": {
45 | "Type": "Task",
46 | "Resource": "ARN:OF:final-state-lambda",
47 | "End": true
48 | }
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/sub_numbers_lambda/handle.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | def lambda_handler(event, context):
4 | number_1 = int(event['key1'])
5 | number_2 = int(event['key2'])
6 | return {"number" : abs(number_1 - number_2)}
7 |
--------------------------------------------------------------------------------
/sub_numbers_lambda/zappa_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "develop": {
3 | "keep_warm": false,
4 | "apigateway_enabled" : false,
5 | "memory_size" : 128,
6 | "debug": false,
7 | "lambda_handler": "handle.lambda_handler"
8 |
9 | }
10 | }
11 |
--------------------------------------------------------------------------------