From f7597f8eca66c05822734d9632ddcc024a023781 Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:22:50 +0200 Subject: [PATCH 1/9] Lambda.py: fix name typo with file rename lamda.py --> lambda.py --- lamda.py => lambda.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lamda.py => lambda.py (100%) diff --git a/lamda.py b/lambda.py similarity index 100% rename from lamda.py rename to lambda.py From 83811416f5322d571b0946c9e5d37a089cb51c68 Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:30:36 +0200 Subject: [PATCH 2/9] Lambda.tf: add terraform config for lambda function --- terraform/lambda.tf | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 terraform/lambda.tf diff --git a/terraform/lambda.tf b/terraform/lambda.tf new file mode 100644 index 0000000..d5ac57e --- /dev/null +++ b/terraform/lambda.tf @@ -0,0 +1,51 @@ +## +## based on an excellent terrform for lambda example: +## https://www.terraform.io/docs/providers/aws/guides/serverless-with-aws-lambda-and-api-gateway.html +## + + +provider "aws" { + region = "eu-central-1" + } + +variable "app_version" { +} + +resource "aws_lambda_function" "PyLambdaFunction" { + function_name = "PythonEvalLambda" + + # The bucket name as created earlier with "aws s3api create-bucket" + s3_bucket = "terraform-serverless-python" + s3_key = "v${var.app_version}/python.zip" + + # "main" is the filename within the zip file (main.py) and "handler" + # is the name of the property under which the handler function was + # exported in that file. + handler = "lambda.lambda_handler" + runtime = "python3.6" + + role = "${aws_iam_role.lambda_exec.arn}" +} + + +# IAM role which dictates what other AWS services the Lambda function +# may access. +resource "aws_iam_role" "lambda_exec" { + name = "serverless_lambda_python" + + assume_role_policy = < Date: Fri, 21 Sep 2018 14:33:11 +0200 Subject: [PATCH 3/9] Api_gateway.tf: add terraform config for API Gateway --- terraform/api_gateway.tf | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 terraform/api_gateway.tf diff --git a/terraform/api_gateway.tf b/terraform/api_gateway.tf new file mode 100644 index 0000000..decaa0e --- /dev/null +++ b/terraform/api_gateway.tf @@ -0,0 +1,69 @@ +## API Gateway config + +resource "aws_api_gateway_rest_api" "PyAPI" { + name = "TfServerlessPythonAPI" + description = "API for Serverless Python Application Example" + } + +resource "aws_api_gateway_resource" "ExecutePyResource" { + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + parent_id = "${aws_api_gateway_rest_api.PyAPI.root_resource_id}" + path_part = "pyexecute" + } + +resource "aws_api_gateway_method" "ExecutePyMethod" { + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + resource_id = "${aws_api_gateway_resource.ExecutePyResource.id}" + http_method = "POST" + authorization = "NONE" + } + +## Lambda Integration +resource "aws_api_gateway_integration" "LambdaIntegration" { + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + resource_id = "${aws_api_gateway_resource.ExecutePyResource.id}" + http_method = "${aws_api_gateway_method.ExecutePyMethod.http_method}" + + integration_http_method = "POST" + type = "AWS" + uri = "${aws_lambda_function.PyLambdaFunction.invoke_arn}" + } + + +## API DEPLOYMENT +resource "aws_api_gateway_deployment" "PyAPIDeployment" { + depends_on = [ + "aws_api_gateway_integration.LambdaIntegration" + ] + + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + stage_name = "v1" + } + +## Permission for API Gateway DEPLOYMENT to access Lambda +resource "aws_lambda_permission" "apigw" { + statement_id = "AllowAPIGatewayInvoke" + action = "lambda:InvokeFunction" + function_name = "${aws_lambda_function.PyLambdaFunction.arn}" + principal = "apigateway.amazonaws.com" + + # The /*/* portion grants access from any method on any resource + # within the API Gateway "REST API". + source_arn = "${aws_api_gateway_deployment.PyAPIDeployment.execution_arn}/*/*" + } + +## Permission for API Gateway REST API to access Lambda +resource "aws_lambda_permission" "lambda_permission" { + statement_id = "AllowTfServerlessPythonAPIInvoke" + action = "lambda:InvokeFunction" + function_name = "${aws_lambda_function.PyLambdaFunction.arn}" + principal = "apigateway.amazonaws.com" + + # The /*/*/* part allows invocation from any stage, method and resource path + # within API Gateway REST API. + source_arn = "${aws_api_gateway_rest_api.PyAPI.execution_arn}/*/*/*" + } + +output "base_url" { + value = "${aws_api_gateway_deployment.PyAPIDeployment.invoke_url}" + } From 26a862fb632c3a593461b04c5c17b042f162889a Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:35:01 +0200 Subject: [PATCH 4/9] Api_gateway.tf: add response mapping config for API Gateway --- terraform/api_gateway.tf | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/terraform/api_gateway.tf b/terraform/api_gateway.tf index decaa0e..7c617d2 100644 --- a/terraform/api_gateway.tf +++ b/terraform/api_gateway.tf @@ -1,5 +1,4 @@ ## API Gateway config - resource "aws_api_gateway_rest_api" "PyAPI" { name = "TfServerlessPythonAPI" description = "API for Serverless Python Application Example" @@ -29,6 +28,21 @@ resource "aws_api_gateway_integration" "LambdaIntegration" { uri = "${aws_lambda_function.PyLambdaFunction.invoke_arn}" } +## Response mapping +resource "aws_api_gateway_method_response" "200" { + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + resource_id = "${aws_api_gateway_resource.ExecutePyResource.id}" + http_method = "${aws_api_gateway_method.ExecutePyMethod.http_method}" + status_code = "200" + } + +resource "aws_api_gateway_integration_response" "LambdaIntegrationResponse" { + rest_api_id = "${aws_api_gateway_rest_api.PyAPI.id}" + resource_id = "${aws_api_gateway_resource.ExecutePyResource.id}" + http_method = "${aws_api_gateway_method.ExecutePyMethod.http_method}" + status_code = "${aws_api_gateway_method_response.200.status_code}" + depends_on = ["aws_api_gateway_integration.LambdaIntegration"] + } ## API DEPLOYMENT resource "aws_api_gateway_deployment" "PyAPIDeployment" { From 718eb6f4dc7be114217b7f1951273ad193c287d9 Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:36:21 +0200 Subject: [PATCH 5/9] README: add readme file with deployemnt instructions --- terraform/README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 terraform/README.md diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..018bd6f --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,48 @@ +# howto +Deploy application with terraform + +### Table of Contents +**[Pre-deployment](#pre-deployment)**
+**[Deployment](#deployment)**
+**[Tests](#tests)**
+ + +Pre-deployment +--- + +Zip your python code: + +`zip python.zip lambda.py` + +Create a aws s3 bucket with location constraint: + +`aws s3api create-bucket --bucket=terraform-serverless-python --create-bucket-configuration LocationConstraint=eu-central-1` + +Upload your build artifact into newly created bucket: + +`aws s3 cp python.zip s3://terraform-serverless-python/v1.0.0/python.zip` + + +Deployment +--- + +Deploy your application with your artifact already available in the s3 bucket + +`terraform plan -var="app_version=1.0.0"` + +`terraform apply -var="app_version=1.0.0"` + +You should get an output of your API Gateway *base_url*: + +` +Outputs: +base_url = https://95q1xx0fol.execute-api.eu-central-1.amazonaws.com/v1 +` + +Tests +--- +Test your lambda function via API Gateway with *curl*: + +` +curl -H "Content-Type: application/json" -X POST -d '{"answer":"def sum(x,y):\n return x-y"}' base_url/pyexecute +` From 5865ae52d18fd6c52a95ed192f461659dc39e6c3 Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:41:42 +0200 Subject: [PATCH 6/9] README: add output highlighting --- terraform/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/terraform/README.md b/terraform/README.md index 018bd6f..560a1e9 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -32,17 +32,17 @@ Deploy your application with your artifact already available in the s3 bucket `terraform apply -var="app_version=1.0.0"` -You should get an output of your API Gateway *base_url*: +You should get an output of your API Gateway **base_url**: -` +```python Outputs: base_url = https://95q1xx0fol.execute-api.eu-central-1.amazonaws.com/v1 -` +``` Tests --- -Test your lambda function via API Gateway with *curl*: +Test your lambda function via API Gateway with **curl**: -` +```python curl -H "Content-Type: application/json" -X POST -d '{"answer":"def sum(x,y):\n return x-y"}' base_url/pyexecute -` +``` From 8f72ba6723f96af72dec5d119f5a600a28f7538a Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Fri, 21 Sep 2018 14:47:27 +0200 Subject: [PATCH 7/9] README: update test section with base_url --- terraform/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terraform/README.md b/terraform/README.md index 560a1e9..a088252 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -46,3 +46,5 @@ Test your lambda function via API Gateway with **curl**: ```python curl -H "Content-Type: application/json" -X POST -d '{"answer":"def sum(x,y):\n return x-y"}' base_url/pyexecute ``` + +Update your `assets/main.js` file with new **base_url**. From 26fbcd153afe0a6cc7ff99e42ff90edfe793d383 Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Sun, 7 Oct 2018 15:38:12 +0200 Subject: [PATCH 8/9] .gitignore: update with ignoring terraform state information --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index e43b0f9..8ba446f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .DS_Store +terraform.tfstate +terraform.tfstate.backup +.terraform \ No newline at end of file From 7cd5d9f29043afd428fe8b03f9bd817d72e3456b Mon Sep 17 00:00:00 2001 From: Jan Kogut Date: Sun, 21 Oct 2018 20:34:16 +0200 Subject: [PATCH 9/9] README: update with terraform output base_url command --- terraform/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform/README.md b/terraform/README.md index a088252..2aca2fe 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -32,10 +32,10 @@ Deploy your application with your artifact already available in the s3 bucket `terraform apply -var="app_version=1.0.0"` -You should get an output of your API Gateway **base_url**: +Use `terraform output` to get an output of your API Gateway **base_url**: ```python -Outputs: +terraform output base_url = https://95q1xx0fol.execute-api.eu-central-1.amazonaws.com/v1 ``` @@ -44,7 +44,7 @@ Tests Test your lambda function via API Gateway with **curl**: ```python -curl -H "Content-Type: application/json" -X POST -d '{"answer":"def sum(x,y):\n return x-y"}' base_url/pyexecute +curl -H "Content-Type: application/json" -X POST -d '{"answer":"def sum(x,y):\n return x-y"}' $(terraform output base_url)/pyexecute ``` Update your `assets/main.js` file with new **base_url**.