-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
412 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.ipynb | ||
Dockerfile | ||
api-construct.ts | ||
*.js | ||
*.d.ts | ||
.ipynb_checkpoints | ||
__pycache__ | ||
.DS_Store | ||
cached-dependencies |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
FROM jupyter/minimal-notebook:65761486d5d3 | ||
|
||
USER root | ||
WORKDIR /app | ||
RUN chown jovyan /app | ||
RUN apt update | ||
RUN apt install nodejs npm -y | ||
RUN npm install -g nodemon@1.18.10 | ||
|
||
# Install dependencies | ||
USER jovyan | ||
RUN mkdir cached-dependencies | ||
RUN pip install boto3 --user | ||
RUN pip install flask-restful==0.3.7 --user | ||
COPY ./requirements.txt /app/ | ||
RUN pip install -r requirements.txt --target=./cached-dependencies | ||
|
||
# Copy api files from directory | ||
COPY ./ /app | ||
|
||
CMD ["start.sh", "jupyter", "notebook", "--NotebookApp.token=''"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import apigateway = require('@aws-cdk/aws-apigateway'); | ||
import lambda = require('@aws-cdk/aws-lambda'); | ||
// import s3 = require('@aws-cdk/aws-s3'); | ||
import fs = require('fs'); | ||
import path = require('path'); | ||
|
||
const isFile = (fileName: any) => { | ||
return fs.lstatSync(fileName).isFile(); | ||
} | ||
|
||
export class ApiConstruct extends cdk.Construct { | ||
public pythonDependencies: cdk.Construct; | ||
|
||
constructor(parent: cdk.Construct, name: string) { | ||
super(parent, name); | ||
const api = new apigateway.RestApi(this, 'Api Gateway', { | ||
restApiName: 'Boilerplate Web App Api', | ||
description: 'This is API comes from a boilerplate web app' | ||
}); | ||
|
||
// const slackBotDepenciesLayer = | ||
this.pythonDependencies = new lambda.LayerVersion(this, 'Slackbot Dependencies', { | ||
compatibleRuntimes: [lambda.Runtime.Python37], | ||
code: lambda.Code.directory('./slackbot/myDependencies') | ||
}); | ||
|
||
this.generateApiConstructs('api/endpoints/', api.root); | ||
} | ||
|
||
|
||
private generateApiConstructs(folderPath: any, apiResource: apigateway.IRestApiResource) { | ||
// If folderPath path is not a file recursively call generateApiConstructs on all files in folderPath | ||
if(!isFile(folderPath)) { | ||
const apiChildResource = apiResource.addResource(path.basename(folderPath)); | ||
fs.readdirSync(folderPath).map((fileName) => { | ||
this.generateApiConstructs(path.join(folderPath, fileName), apiChildResource); | ||
}); | ||
return; | ||
}; | ||
// If file is not a api config file exit method | ||
if(!folderPath.endsWith('.api-config.json')) { | ||
return; | ||
} | ||
// If file is a api config file create lambda function and api methods | ||
const configs = require('../' + folderPath); | ||
const basename = path.basename(folderPath, '.api-config.json'); | ||
const dirname = path.dirname(folderPath); | ||
const params = { | ||
runtime: lambda.Runtime.Python37, | ||
code: lambda.Code.directory(dirname), | ||
// layers: [slackBotLayer], | ||
handler: `${basename}.main` | ||
} | ||
const lambdaFunction = new lambda.Function(this, folderPath.replace(/\//g, '_'), params); | ||
const apiLambdaIntegration = new apigateway.LambdaIntegration(lambdaFunction); | ||
configs['methods'].map((method: string) => { | ||
apiResource.addMethod(method, apiLambdaIntegration); | ||
}); | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"methods": [ | ||
"GET", | ||
"POST" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import json | ||
|
||
def get(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
'message': 'GET language', | ||
'event': event | ||
}) | ||
} | ||
|
||
def post(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
'message': 'POST language', | ||
'event': event | ||
}) | ||
} | ||
|
||
def main(event, context): | ||
if event["httpMethod"] == "GET": | ||
return get(event, context) | ||
elif event["httpMethod"] == "POST": | ||
return post(event, context) | ||
elif event["httpMethod"] == "DELETE": | ||
return delete(event, context) | ||
elif event["httpMethod"] == "PUT": | ||
return post(event, context) | ||
else: | ||
return { | ||
"statusCode": 405, | ||
"body": json.dumps( | ||
{ | ||
"message": "Method Not Allowed" | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"methods": [ | ||
"GET" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import json | ||
|
||
def get(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
'message': 'GET Breed', | ||
'event': event | ||
}) | ||
} | ||
|
||
def main(event, context): | ||
if event["httpMethod"] == "GET": | ||
return get(event, context) | ||
elif event["httpMethod"] == "POST": | ||
return post(event, context) | ||
elif event["httpMethod"] == "DELETE": | ||
return delete(event, context) | ||
elif event["httpMethod"] == "PUT": | ||
return post(event, context) | ||
else: | ||
return { | ||
"statusCode": 405, | ||
"body": json.dumps( | ||
{ | ||
"message": "Method Not Allowed" | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"methods": [ | ||
"GET", | ||
"POST" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import json | ||
import numpy as np | ||
|
||
|
||
def get(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
'message': 'GET test', | ||
'event': event | ||
}) | ||
} | ||
|
||
def post(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
'message': 'POST test', | ||
'event': event | ||
}) | ||
} | ||
|
||
def main(event, context): | ||
if event["httpMethod"] == "GET": | ||
return get(event, context) | ||
elif event["httpMethod"] == "POST": | ||
return post(event, context) | ||
elif event["httpMethod"] == "DELETE": | ||
return delete(event, context) | ||
elif event["httpMethod"] == "PUT": | ||
return post(event, context) | ||
else: | ||
return { | ||
"statusCode": 405, | ||
"body": json.dumps( | ||
{ | ||
"message": "Method Not Allowed" | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
numpy==1.16.0 | ||
pandas==0.24.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# Add /cached-dependencies/ to importable path | ||
import sys | ||
import os | ||
import importlib | ||
import json | ||
|
||
sys.path.append('./cached-dependencies') | ||
|
||
from flask import Flask, request | ||
from flask_restful import Api, Resource, reqparse | ||
class Test(Resource): | ||
def get(self): | ||
print(self) | ||
return 'SS', 200 | ||
app = Flask(__name__) | ||
api = Api(app) | ||
|
||
|
||
# Template JSON/Dicts that represent a AWS lambda events for every HTTP method | ||
get_lambda_event_template = { | ||
'httpMethod': 'GET', | ||
'queryStringParameters': {}, | ||
'pathParameters': None, | ||
'requestContext': { | ||
'identity': { | ||
'accessKey': None, | ||
'accountId': None, | ||
'caller': None, | ||
'cognitoAuthenticationProvider': None, | ||
'cognitoAuthenticationType': None, | ||
'cognitoIdentityId': None, | ||
'cognitoIdentityPoolId': None | ||
} | ||
} | ||
} | ||
post_lambda_event_template = { | ||
'httpMethod': 'POST', | ||
'body': {}, | ||
'queryStringParameters': {}, | ||
'pathParameters': None, | ||
'requestContext': { | ||
'identity': { | ||
'accessKey': None, | ||
'accountId': None, | ||
'caller': None, | ||
'cognitoAuthenticationProvider': None, | ||
'cognitoAuthenticationType': None, | ||
'cognitoIdentityId': None, | ||
'cognitoIdentityPoolId': None | ||
} | ||
} | ||
} | ||
put_lambda_event_template = { | ||
'httpMethod': 'POST', | ||
'body': {}, | ||
'queryStringParameters': {}, | ||
'requestContext': { | ||
'identity': { | ||
'accessKey': None, | ||
'accountId': None, | ||
'caller': None, | ||
'cognitoAuthenticationProvider': None, | ||
'cognitoAuthenticationType': None, | ||
'cognitoIdentityId': None, | ||
'cognitoIdentityPoolId': None | ||
} | ||
} | ||
} | ||
delete_lambda_event_template = { | ||
'httpMethod': 'POST', | ||
'body': {}, | ||
'queryStringParameters': {}, | ||
'requestContext': { | ||
'identity': { | ||
'accessKey': None, | ||
'accountId': None, | ||
'caller': None, | ||
'cognitoAuthenticationProvider': None, | ||
'cognitoAuthenticationType': None, | ||
'cognitoIdentityId': None, | ||
'cognitoIdentityPoolId': None | ||
} | ||
} | ||
} | ||
|
||
endpoint_dir = './endpoints' | ||
|
||
|
||
# Construct Flask API endpoints based on folder structure of endpoint folder | ||
i=0 | ||
for path, dirs, files in os.walk(endpoint_dir): | ||
i+=1 | ||
full_path = os.path.abspath(path) | ||
current_folder_name = full_path.split(os.sep)[-1] | ||
# If a python file for lambda function exists for the resource do the following: | ||
if f'{current_folder_name}.py' in files: | ||
api_resource_path = path.replace(endpoint_dir, '').replace('{', '<').replace('}', '>') | ||
full_path_of_py_file = os.path.abspath(path) + f'/{current_folder_name}.py' | ||
|
||
spec = importlib.util.spec_from_file_location("module.name", full_path_of_py_file) | ||
current_lambda_module = importlib.util.module_from_spec(spec) | ||
spec.loader.exec_module(current_lambda_module) | ||
|
||
|
||
# Creating an Anonomys Class | ||
class LambdaApiResource(Resource): | ||
resource = api_resource_path | ||
lambda_module = current_lambda_module | ||
get_lambda_event = get_lambda_event_template.copy() | ||
post_lambda_event = post_lambda_event_template.copy() | ||
put_lambda_event = put_lambda_event_template.copy() | ||
delete_lambda_event = delete_lambda_event_template.copy() | ||
|
||
def get(self, **kwargs): | ||
print(request.args) | ||
get_lambda_event = self.get_lambda_event.copy() | ||
get_lambda_event['pathParameters'] = kwargs | ||
get_lambda_event['queryStringParameters'] = {key:val for key, val in request.args.items()} | ||
lambda_result = self.lambda_module.main( | ||
get_lambda_event, | ||
None | ||
) | ||
return json.loads(lambda_result['body']), lambda_result['statusCode'] | ||
def post(self, **kwargs): | ||
post_lambda_event = self.post_lambda_event.copy() | ||
post_lambda_event['pathParameters'] = kwargs | ||
post_lambda_event['queryStringParameters'] = {key:val for key, val in request.args.items()} | ||
lambda_result = self.lambda_module.main( | ||
post_lambda_event, | ||
None | ||
) | ||
return json.loads(lambda_result['body']), lambda_result['statusCode'] | ||
def put(self, **kwargs): | ||
put_lambda_event = self.put_lambda_event.copy() | ||
put_lambda_event['pathParameters'] = kwargs | ||
put_lambda_event['queryStringParameters'] = {key:val for key, val in request.args.items()} | ||
lambda_result = self.lambda_module.main( | ||
put_lambda_event, | ||
None | ||
) | ||
return json.loads(lambda_result['body']), lambda_result['statusCode'] | ||
def delete(self, **kwargs): | ||
delete_lambda_event = self.delete_lambda_event.copy() | ||
delete_lambda_event['pathParameters'] = kwargs | ||
delete_lambda_event['queryStringParameters'] = {key:val for key, val in request.args.items()} | ||
lambda_result = self.lambda_module.main( | ||
post_lambda_event, | ||
None | ||
) | ||
return json.loads(lambda_result['body']), lambda_result['statusCode'] | ||
|
||
LambdaApiResource.__name__ = f'Lambda{i}' | ||
api.add_resource(LambdaApiResource, api_resource_path) | ||
|
||
app.run(host='0.0.0.0', port=10000, debug=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.