Skip to content

Commit 05c8d71

Browse files
committed
first take
1 parent aacddb7 commit 05c8d71

34 files changed

+1500
-0
lines changed

.gitattributes

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Set the default CRLF behavior
2+
* text=auto
3+
4+
# Explicitly declare text files you want to always be normalized and converted
5+
# to native line endings on checkout.
6+
*.Rmd text
7+
*.R text
8+
*.py text
9+
10+
# Declare files that will always have CRLF line endings on checkout.
11+
*.sh text eol=lf

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# aws-lambda-r
2+
23
Using R on AWS Lambda

doc/AWS-setup.md

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# aws-lambda-r - Configure AWS for production deployment
2+
3+
**Note: the detailed instructions are not complete.** If you are familiar with AWS,
4+
please review the files in `scripts/` and `settings/`.
5+
6+
These are instructions to be followed before running the scripts. At the end of
7+
these instruction you should have obtained the values for the following keys:
8+
9+
```
10+
IAM_ACCESS_KEY_ID=""
11+
IAM_SECRET_ACCESS_KEY=""
12+
IAM_LAMBDA_FUNCTION_ROLE=""
13+
EC2_KEY_NAME=""
14+
EC2_KEY_FILE=""
15+
EC2_SECURITY_GROUP_IDS=""
16+
EC2_SUBNET_ID=""
17+
S3_BUCKET=""
18+
API_ID=""
19+
API_RESOURCE_ID=""
20+
API_ALIAS_RESOURCE_ID=""
21+
API_AUTHORIZER_ID=""
22+
API_TOKEN=""
23+
```
24+
25+
26+
27+
28+
## IAM
29+
30+
IAM manages access to AWS.
31+
32+
1. Create an IAM user account to be used only in conjunction with this app
33+
+ retain the values of **ACCESS_KEY_ID** and **SECRET_ACCESS_KEY**
34+
2. Give necessary permissions to this user
35+
+ [TBD: more automation --> more permissions]
36+
3. Create roles and policies
37+
+ attach policies to the roles
38+
39+
40+
## SSH Key
41+
42+
SSH Keys allows access through an SSH tunnel to a remove / cloud AWS EC2 instance.
43+
44+
### Create and save SSH key for EC2 connection
45+
46+
1. Log in to AWS Console.
47+
2. Go to EC2 Service
48+
3. Select **Key Pairs** under **NETWORK & SECURITY** menu.
49+
50+
![Key Pairs menu](ssh-01-key-pairs-menu.png)
51+
52+
4. Press "Create Key Pair" button and give it a name. When you press the
53+
"Create" button, the browser will start downloading the key automatically.
54+
55+
![Enter key pair name](ssh-02-enter-key-pair-name.png)
56+
57+
5. Open the folder containing downloaded key (a `.pem` file having the same name as the created key)
58+
59+
6. Copy the `.pem` file to:
60+
- on Windows: `C:\Users\<your_user_Name>/.ssh/` folder
61+
+ in order to show hidden folders go to Folder Menu > View > Check "Hidden items"
62+
- on OSX and Linux: `~/.ssh/` Additional commands might be necessary from terminal:
63+
+ `chmod 700 ~/.ssh`
64+
+ `chmod 400 ~/.ssh/<your_key_file>.pem`
65+
+ other instructions: [1](https://unix.stackexchange.com/a/115860) and
66+
[2](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html)
67+
68+
69+
## VPC [automate ?]
70+
71+
1. Create dedicate VPC
72+
2. Create subnet
73+
3. Create security group
74+
75+
76+
## LAMBDA [automate ?]
77+
78+
1. Create Lambda Authorizer function
79+
80+
81+
## S3 BUCKET [automate ?]
82+
83+
1. Create S3 bucket
84+
85+
86+
## API GATEWAY
87+
88+
1. Create API
89+
2. Create resources
90+
3. Create authorizer
91+
4. Create stages
92+
5. Attach role for CloudWatch logging to API
93+
6. Enable CloudWatch Logging on stages
94+
95+
96+
## TERMINATE UNUSED INSTANCES
97+
98+
1. Go to AWS web console and select Frankfurt / eu-central-1 region
99+
2. To to EC2 > Instances
100+
3. Select all running instance > Actions button > Instance State > Terminate
101+
102+
## Create Custom Settings file
103+
104+
[steps needed to create "secrets_user.sh" and "setup_user_secrets.sh" files]

doc/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# aws-lambda-r - doc
2+
3+
Documentation directory

doc/lambda-policy.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Action": [
7+
"logs:CreateLogGroup",
8+
"logs:CreateLogStream",
9+
"logs:PutLogEvents"
10+
],
11+
"Resource": "arn:aws:logs:*:*:*"
12+
}
13+
]
14+
}

doc/lambda-trust.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Principal": {
7+
"Service": "lambda.amazonaws.com"
8+
},
9+
"Action": "sts:AssumeRole"
10+
}
11+
]
12+
}

doc/ssh-01-key-pairs-menu.png

47.9 KB
Loading

doc/ssh-02-enter-key-pair-name.png

6.54 KB
Loading

example.R

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# library(jsonlite)
2+
3+
4+
from_json <- function(json) {
5+
6+
# basic exceptions
7+
if (length(json) == 0L || is.na(json) || nchar(json) == 2L) json <- '{}'
8+
9+
jsonlite::fromJSON(json)
10+
}
11+
12+
13+
to_json <- function(lst) {
14+
15+
jsonlite::toJSON(
16+
lst,
17+
dataframe = 'rows',
18+
null = 'list',
19+
na = 'null',
20+
auto_unbox = TRUE,
21+
digits = NA,
22+
pretty = TRUE
23+
)
24+
}
25+
26+
27+
# pure function (preferable), receives a json and returns a json
28+
aws_lambda_r <- function(input_json) {
29+
30+
# generic default error message
31+
# defined only to illustrate how the function works
32+
output_json <- '{"message": "Cannot create output JSON"}'
33+
34+
# possible implementation: catch all errors
35+
tryCatch({
36+
input_lst <- from_json(input_json)
37+
request_id <- input_lst$request_id[1]
38+
39+
output_lst <- list(
40+
result_id = request_id,
41+
result_lst = list(a = 1, b = 2:4),
42+
result_dbl = 1:10 / 2,
43+
message = NULL,
44+
)
45+
46+
output_json <- to_json(output_lst)
47+
48+
}, error = function(e) {
49+
output_json <<- paste0('{"message": "', e$message, '"}')
50+
})
51+
52+
output_json
53+
}

lambda/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Ignore everything in this directory
2+
*
3+
# Except files below
4+
!.gitignore
5+
!README.md

lambda/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# aws-lambda-r - lambda
2+
3+
All the files in this dir will used to create the AWS Lambda deployment package.
4+
5+
- Temporary dir, NOT tracked by git!
6+
- The content of this dir will be updated automatically
7+
- Please do not add extra files that are not being used by lambda

python/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# aws-lambda-r - python
2+
3+
Python files, used for lambda

python/lambda_post.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
import ctypes
3+
import rpy2.robjects as robjects
4+
import json
5+
6+
os.environ["R_HOME"] = os.getcwd()
7+
os.environ["R_LIBS"] = os.path.join(os.getcwd(), 'libraries')
8+
9+
for file in os.listdir('lib/external'):
10+
file_name='lib/external/' + file
11+
ctypes.cdll.LoadLibrary(os.path.join(os.getcwd(), file_name))
12+
13+
14+
# source R file
15+
# this R file might load libraries and source other files
16+
robjects.r['source']('example.R')
17+
18+
# exposing R entry point to python
19+
aws_lambda_r = robjects.globalenv['aws_lambda_r']
20+
21+
22+
def handler_post(event, context):
23+
24+
input_json = json.dumps(event)
25+
output_json = aws_lambda_r(input_json)
26+
27+
return output_json

scripts/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# List files to ignore

scripts/01_main.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
# calls all other local scripts
4+
5+
6+
# load local settings if not already loaded
7+
[[ $SCR_DIR ]] || SCR_DIR="$(cd "$(dirname "$0")/."; pwd)"
8+
[[ $PRJ_DIR ]] || source "$SCR_DIR/02_setup.sh"
9+
10+
11+
12+
source "$SCR_DIR/03_check_settings.sh"
13+
14+
source "$SCR_DIR/04_create_ec2.sh"
15+
source "$SCR_DIR/05_update_ec2.sh"
16+
17+
source "$SCR_DIR/06_copy_files.sh"
18+
19+
source "$SCR_DIR/07_deploy_lambda.sh"
20+
21+
source "$SCR_DIR/08_terminate_ec2.sh"
22+
23+
source "$SCR_DIR/09_test_deployment.sh"
24+
25+
26+
echo -e "$INFO End of $(basename $0) script"

0 commit comments

Comments
 (0)