├── go.mod ├── Dockerfile ├── main.go ├── infrastructure ├── terraform.tfvars ├── variables.tf ├── domain.tf ├── main.tf └── api-gateway.tf ├── .gitignore ├── cmd └── handler │ └── main.go ├── handlers └── handler.go ├── go.sum ├── LICENSE ├── create-ecr.sh └── README.md /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/JayJamieson/go-lambda 2 | 3 | go 1.22 4 | 5 | require github.com/aws/aws-lambda-go v1.48.0 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.22 AS build 2 | 3 | WORKDIR /project 4 | 5 | COPY go.mod go.sum ./ 6 | RUN go mod download -x 7 | 8 | COPY handlers/ handlers/ 9 | COPY main.go . 10 | 11 | RUN CGO_ENABLED=0 go build -tags lambda.norpc -o main main.go 12 | 13 | FROM public.ecr.aws/lambda/provided:al2 14 | 15 | COPY --from=build /project/main ./main 16 | 17 | ENTRYPOINT [ "./main" ] 18 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/JayJamieson/go-lambda/handlers" 5 | "github.com/aws/aws-lambda-go/lambda" 6 | ) 7 | 8 | func main() { 9 | // https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html 10 | // New returns handler function this is useful for passing 11 | // in environment configurations and dependencies 12 | 13 | handler := handlers.New() 14 | lambda.Start(handler) 15 | } 16 | -------------------------------------------------------------------------------- /infrastructure/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # Uncomment this to enable deployment of API Gateway 2 | # with_api_gateway = true 3 | 4 | # Replace with real domain owned in Route53 5 | root_zone_domain = "example.com." 6 | lambda_rest_api_sub_domain_name = "lambda.example.com" 7 | region = "ap-southeast-2" 8 | 9 | repo_name = "go-lambda" 10 | ecr_repository_uri = "111122223333.dkr.ecr.ap-southeast-2.amazonaws.com" 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | bin/main 17 | bin/main.local 18 | function.zip 19 | bootstrap 20 | 21 | .idea 22 | infrastructure/.terraform 23 | infrastructure/.terraform.lock.hcl 24 | infrastructure/.terraform/providers/registry.terraform.io/hashicorp/aws/5.13.1/linux_amd64/terraform-provider-aws_v5.13.1_x5 25 | infrastructure/terraform.tfstate 26 | infrastructure/terraform.tfstate.backup 27 | -------------------------------------------------------------------------------- /cmd/handler/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "github.com/JayJamieson/go-lambda/handlers" 6 | "log" 7 | "os" 8 | "time" 9 | 10 | "github.com/aws/aws-lambda-go/events" 11 | ) 12 | 13 | func main() { 14 | //this lambda setup is used for testing/running locally without deployment 15 | //if specific events are required we can read in json event samples or 16 | //command line flags to help build the events 17 | 18 | lambdaMaxRuntime := time.Now().Add(15 * time.Minute) 19 | 20 | ctx, cancel := context.WithDeadline(context.Background(), lambdaMaxRuntime) 21 | defer cancel() 22 | 23 | handler := handlers.New() 24 | 25 | // setup event from cli args or reading from file 26 | event := events.APIGatewayProxyRequest{} 27 | 28 | _, err := handler(ctx, event) 29 | 30 | if err != nil { 31 | log.Fatal(err.Error()) 32 | } 33 | 34 | os.Exit(0) 35 | } 36 | -------------------------------------------------------------------------------- /handlers/handler.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "log" 8 | 9 | "github.com/aws/aws-lambda-go/events" 10 | ) 11 | 12 | func New() func(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 13 | // similar to http middlewares, initialize dependencies here and use in 14 | // returned handler function. 15 | return func(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 16 | hello, ok := request.QueryStringParameters["hello"] 17 | req, _ := json.Marshal(request) 18 | 19 | log.Print(string(req)) 20 | 21 | resp := "Hello World" 22 | if ok { 23 | resp = fmt.Sprintf("Hello %v 👀", hello) 24 | } 25 | log.Print("Running lambda") 26 | defer log.Print("Lambda complete") 27 | return events.APIGatewayProxyResponse{Body: resp, StatusCode: 200}, nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/aws/aws-lambda-go v1.41.0 h1:l/5fyVb6Ud9uYd411xdHZzSf2n86TakxzpvIoz7l+3Y= 2 | github.com/aws/aws-lambda-go v1.41.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM= 3 | github.com/aws/aws-lambda-go v1.48.0 h1:1aZUYsrJu0yo5fC4z+Rba1KhNImXcJcvHu763BxoyIo= 4 | github.com/aws/aws-lambda-go v1.48.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= 10 | github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 11 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 12 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 13 | -------------------------------------------------------------------------------- /infrastructure/variables.tf: -------------------------------------------------------------------------------- 1 | variable "root_zone_domain" { 2 | description = "name of root domain name zone used for creating certificates and domain names" 3 | default = "example.com." 4 | } 5 | 6 | variable "lambda_rest_api_sub_domain_name" { 7 | description = "domain name for api gateway and certificates" 8 | default = "api.example.com" 9 | } 10 | 11 | variable "ecr_repository_uri" { 12 | description = "URI of AWS ECR" 13 | nullable = false 14 | } 15 | 16 | variable "repo_name" { 17 | description = "Name of ECR repo" 18 | nullable = false 19 | } 20 | 21 | variable "image_tag" { 22 | description = "Container image tag" 23 | default = "latest" 24 | } 25 | 26 | variable "with_api_gateway" { 27 | description = "Deploy with API Gateway" 28 | type = bool 29 | default = false 30 | } 31 | 32 | variable "region" { 33 | description = "deployment region" 34 | default = "ap-southeast-2" 35 | } 36 | 37 | variable "with_docker_build" { 38 | description = "Include automatic build step as part of terraform apply" 39 | type = bool 40 | default = false 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 JayJamieson 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. -------------------------------------------------------------------------------- /create-ecr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | GREEN="\e[32m" 6 | RED="\e[31m" 7 | YELLOW="\e[33m" 8 | NC="\e[0m" 9 | 10 | trap 'echo -e "${RED}Error on line ${LINENO}. Aborting.${NC}" >&2; exit 1' ERR 11 | 12 | usage() { 13 | cat <&2 14 | Usage: $0 --repo-name NAME --region REGION --account-id ID [--auth-only] 15 | --repo-name ECR repository name (required) 16 | --region AWS region (required) 17 | --account-id AWS account ID (required) 18 | --auth-only Only login Docker to ECR and exit 19 | EOF 20 | exit 1 21 | } 22 | 23 | REPO_NAME="" 24 | REGION="" 25 | ACCOUNT_ID="" 26 | AUTH_ONLY=false 27 | 28 | while [[ $# -gt 0 ]]; do 29 | case "$1" in 30 | --repo-name) REPO_NAME="$2"; shift 2 ;; 31 | --region) REGION="$2"; shift 2 ;; 32 | --account-id) ACCOUNT_ID="$2"; shift 2 ;; 33 | --auth-only) AUTH_ONLY=true; shift ;; 34 | -h|--help) usage ;; 35 | *) echo -e "${RED}Unknown option: $1${NC}" >&2; usage ;; 36 | esac 37 | done 38 | 39 | [[ -n "$REPO_NAME" && -n "$REGION" && -n "$ACCOUNT_ID" ]] || usage 40 | 41 | ECR_URI="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com" 42 | 43 | echo -e "${YELLOW}Logging in to ECR registry ${ECR_URI}…${NC}" >&2 44 | aws ecr get-login-password --region "$REGION" \ 45 | | docker login --username AWS --password-stdin "${ECR_URI}" \ 46 | && echo -e "${GREEN}Docker login succeeded.${NC}" >&2 47 | 48 | if $AUTH_ONLY; then 49 | echo -e "${YELLOW}Auth-only flag set; exiting after login.${NC}" >&2 50 | exit 0 51 | fi 52 | 53 | echo -e "${YELLOW}Creating ECR repository '${REPO_NAME}'…${NC}" >&2 54 | CREATE_OUTPUT=$(aws ecr create-repository \ 55 | --repository-name "$REPO_NAME" \ 56 | --region "$REGION" \ 57 | --image-scanning-configuration scanOnPush=false \ 58 | --image-tag-mutability MUTABLE) 59 | echo -e "${GREEN}Repository creation succeeded.${NC}" >&2 60 | 61 | REPO_URI=$(echo "$CREATE_OUTPUT" | jq -r '.repository.repositoryUri') 62 | echo -e "Repository URI: $REPO_URI" >&2 63 | 64 | printf '%s\n' "$REPO_URI" 65 | -------------------------------------------------------------------------------- /infrastructure/domain.tf: -------------------------------------------------------------------------------- 1 | data "aws_route53_zone" "lambda_api_root_zone" { 2 | count = var.with_api_gateway ? 1 : 0 3 | name = var.root_zone_domain 4 | } 5 | 6 | resource "aws_acm_certificate" "certificate" { 7 | count = var.with_api_gateway ? 1 : 0 8 | domain_name = var.lambda_rest_api_sub_domain_name 9 | validation_method = "DNS" 10 | } 11 | 12 | resource "aws_route53_record" "certificate_validation" { 13 | count = var.with_api_gateway ? 1 : 0 14 | name = tolist(aws_acm_certificate.certificate[0].domain_validation_options)[0].resource_record_name 15 | type = tolist(aws_acm_certificate.certificate[0].domain_validation_options)[0].resource_record_type 16 | zone_id = data.aws_route53_zone.lambda_api_root_zone[0].zone_id 17 | records = [tolist(aws_acm_certificate.certificate[0].domain_validation_options)[0].resource_record_value] 18 | ttl = 60 19 | } 20 | 21 | resource "aws_acm_certificate_validation" "certificate_validation" { 22 | count = var.with_api_gateway ? 1 : 0 23 | certificate_arn = aws_acm_certificate.certificate[0].arn 24 | validation_record_fqdns = [aws_route53_record.certificate_validation[0].fqdn] 25 | } 26 | 27 | resource "aws_api_gateway_domain_name" "domain_name" { 28 | count = var.with_api_gateway ? 1 : 0 29 | domain_name = var.lambda_rest_api_sub_domain_name 30 | regional_certificate_arn = aws_acm_certificate_validation.certificate_validation[0].certificate_arn 31 | 32 | endpoint_configuration { 33 | types = [ 34 | "REGIONAL", 35 | ] 36 | } 37 | } 38 | 39 | resource "aws_api_gateway_base_path_mapping" "path_mapping" { 40 | count = var.with_api_gateway ? 1 : 0 41 | api_id = aws_api_gateway_rest_api.lambda_api[0].id 42 | stage_name = aws_api_gateway_stage.lambda_api_stage[0].stage_name 43 | domain_name = aws_api_gateway_domain_name.domain_name[0].domain_name 44 | } 45 | 46 | resource "aws_route53_record" "sub_domain" { 47 | count = var.with_api_gateway ? 1 : 0 48 | name = var.lambda_rest_api_sub_domain_name 49 | type = "A" 50 | zone_id = data.aws_route53_zone.lambda_api_root_zone[0].zone_id 51 | 52 | alias { 53 | name = aws_api_gateway_domain_name.domain_name[0].regional_domain_name 54 | zone_id = aws_api_gateway_domain_name.domain_name[0].regional_zone_id 55 | evaluate_target_health = false 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-lambda 2 | 3 | **AWS has [deprecated go1.x](https://aws.amazon.com/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/) runtime.** 4 | 5 | This repository contains example lambda handler integration with API Gateway. Terraform is used to deploy infrastructure including DNS, SSL Certificates. 6 | 7 | ## Requirements 8 | 9 | - go 1.22 10 | - zip 11 | - docker 12 | - terraform 13 | - aws cli 14 | - jq 15 | 16 | ## Setup (Optional) 17 | 18 | For now an existing AWS ECR is required to exist already or created using `./create_ecr.sh`. Unfortunately it's not possible yet to create an ECR, build and push an image, then reference the image_uri needed for Lambda resource. 19 | 20 | If you an existing ECR you can run `./create_ecr.sh` with the `--auth-only` flag to skip creating a new ECR. This will pull credentials and inject into Docker engine. 21 | 22 | ```shell 23 | Usage: ./create-ecr.sh --repo-name NAME --region REGION --account-id ID [--auth-only] 24 | --repo-name ECR repository name (required) 25 | --region AWS region (required) 26 | --account-id AWS account ID (required) 27 | --auth-only Only login Docker to ECR and exit 28 | ``` 29 | 30 | ## Build 31 | 32 | The deploy artifact is a container image instead of a zip file with the built binary. AWS has optimized container images for Lambda and results in faster cold starts. 33 | 34 | To build an image and tag using `tag --points-at HEAD --sort=-version:refname` run `./build_image.sh`. This script will built a Lambda compatible container image and push to the configured AWS ECR. This script expects `./create_ecr.sh` to have run or at the minimum run with `--auth-only` for an existing ECR to get login credentials for Docker engine. 35 | 36 | ```shell 37 | Usage: ./build_image.sh --account-id ID --region REGION --repo-name NAME [--tag TAG] 38 | --account-id AWS account ID (required) 39 | --region AWS region (required) 40 | --repo-name ECR repository name (required) 41 | --tag Image tag override; if omitted, use latest Git tag on HEAD 42 | ``` 43 | 44 | If you want to create and push smaller slim images then please install [slimtoolkit/slim](https://github.com/slimtoolkit/slim). You can then optionally pass `--slim-image` to minify images and push to ECR. 45 | 46 | ## Deploy 47 | 48 | Create a `terraform.tfvars` file inside infrastructure folder and fill out required variables. 49 | 50 | - Use terraform to deploy infrastructure changes and function changes `terraform apply --auto-approve` 51 | 52 | To enable auto container image builds set `with_docker_build` to `true`. This will run the `./build_image.sh` script and output the image URI for use in the Lambda resource. Default is disabled. 53 | 54 | ## Optional 55 | 56 | Currently, the lambda handler takes in any request method and path. For full utilization of API Gateway proxy functionality you can make use of to run a standard Go http server and adapt API Gateway requests to Go requests and vice versa Go responses to API Gateway responses 57 | 58 | - Be aware to write lambda aware handlers using the adapters. 59 | - Optimize for fast startups 60 | 61 | ## Future work 62 | 63 | - [ ] add GitHub action to build and deploy changes on main branch merge 64 | -------------------------------------------------------------------------------- /infrastructure/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~> 5.13.1" 6 | } 7 | } 8 | } 9 | 10 | provider "aws" { 11 | region = var.region 12 | } 13 | 14 | data "aws_caller_identity" "current" {} 15 | 16 | data "external" "ecr_image" { 17 | count = var.with_docker_build ? 1 : 0 18 | 19 | program = [ 20 | "bash", "-c", 21 | <<-EOC 22 | # change into the parent directory of this module 23 | cd "${path.module}/.." && \ 24 | # invoke your build script with all required flags (and optional tag) 25 | ./build_image.sh \ 26 | --account-id "${data.aws_caller_identity.current.account_id}" \ 27 | --region "${var.region}" \ 28 | --repo-name "${var.repo_name}" \ 29 | ${var.image_tag != "" ? "--tag ${var.image_tag}" : ""} \ 30 | EOC 31 | ] 32 | 33 | } 34 | 35 | resource "aws_lambda_function" "go_lambda" { 36 | function_name = "go-demo" 37 | 38 | role = aws_iam_role.lambda_iam_role.arn 39 | architectures = ["x86_64"] 40 | 41 | image_uri = var.with_docker_build == true ? data.external.ecr_image[0].result.image_uri : "${var.ecr_repository_uri}/${var.repo_name}:${var.image_tag}" 42 | 43 | package_type = "Image" 44 | timeout = 900 45 | 46 | depends_on = [ 47 | aws_iam_role_policy_attachment.lambda_policy_attachment, 48 | data.external.ecr_image 49 | ] 50 | } 51 | 52 | resource "aws_lambda_function_url" "go_lambda" { 53 | function_name = aws_lambda_function.go_lambda.function_name 54 | authorization_type = "NONE" 55 | } 56 | 57 | resource "aws_iam_role" "lambda_iam_role" { 58 | name = "demo-lambda-execution-role" 59 | assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json 60 | } 61 | 62 | data "aws_iam_policy_document" "lambda_assume_role_policy" { 63 | statement { 64 | actions = ["sts:AssumeRole"] 65 | 66 | principals { 67 | type = "Service" 68 | identifiers = ["lambda.amazonaws.com"] 69 | } 70 | } 71 | } 72 | 73 | resource "aws_iam_policy" "lambda_execution_policy" { 74 | name = "demo-lambda-basic-execution-policy" 75 | description = "policy to allow basic execution of lambda" 76 | 77 | policy = jsonencode({ 78 | Version = "2012-10-17" 79 | Statement = [ 80 | { 81 | Action = ["logs:CreateLogGroup"] 82 | Effect = "Allow" 83 | Resource = [ 84 | "arn:aws:logs:${var.region}:${data.aws_caller_identity.current.account_id}:*" 85 | ] 86 | }, 87 | { 88 | Effect = "Allow", 89 | Action = [ 90 | "logs:CreateLogStream", 91 | "logs:PutLogEvents" 92 | ], 93 | Resource = "arn:aws:logs:${var.region}:${data.aws_caller_identity.current.account_id}:log-group:*" 94 | } 95 | ] 96 | }) 97 | } 98 | 99 | resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" { 100 | role = aws_iam_role.lambda_iam_role.name 101 | policy_arn = aws_iam_policy.lambda_execution_policy.arn 102 | } 103 | 104 | output "lambda_function_arn" { 105 | value = aws_lambda_function.go_lambda.invoke_arn 106 | } 107 | 108 | output "lambda_function_name" { 109 | value = aws_lambda_function.go_lambda.function_name 110 | } 111 | 112 | output "lambda_function_url" { 113 | value = aws_lambda_function_url.go_lambda.function_url 114 | } 115 | -------------------------------------------------------------------------------- /infrastructure/api-gateway.tf: -------------------------------------------------------------------------------- 1 | resource "aws_api_gateway_rest_api" "lambda_api" { 2 | count = var.with_api_gateway ? 1 : 0 3 | name = "lambda-api" 4 | endpoint_configuration { 5 | types = ["REGIONAL"] 6 | } 7 | disable_execute_api_endpoint = true 8 | } 9 | 10 | resource "aws_api_gateway_resource" "lambda_api_resource" { 11 | count = var.with_api_gateway ? 1 : 0 12 | rest_api_id = aws_api_gateway_rest_api.lambda_api[0].id 13 | parent_id = aws_api_gateway_rest_api.lambda_api[0].root_resource_id 14 | path_part = "{proxy+}" 15 | } 16 | 17 | resource "aws_api_gateway_method" "method" { 18 | count = var.with_api_gateway ? 1 : 0 19 | rest_api_id = aws_api_gateway_rest_api.lambda_api[0].id 20 | resource_id = aws_api_gateway_resource.lambda_api_resource[0].id 21 | http_method = "ANY" 22 | authorization = "NONE" 23 | api_key_required = true 24 | } 25 | 26 | resource "aws_api_gateway_deployment" "lambda_api_deployment" { 27 | count = var.with_api_gateway ? 1 : 0 28 | rest_api_id = aws_api_gateway_rest_api.lambda_api[0].id 29 | triggers = { 30 | redeployment = sha1(jsonencode([ 31 | aws_api_gateway_resource.lambda_api_resource[0].id, 32 | aws_api_gateway_method.method[0].id, 33 | aws_api_gateway_integration.lambda_integration[0].id 34 | ])) 35 | } 36 | lifecycle { 37 | create_before_destroy = true 38 | } 39 | } 40 | 41 | resource "aws_api_gateway_stage" "lambda_api_stage" { 42 | count = var.with_api_gateway ? 1 : 0 43 | deployment_id = aws_api_gateway_deployment.lambda_api_deployment[0].id 44 | rest_api_id = aws_api_gateway_rest_api.lambda_api[0].id 45 | stage_name = "production" 46 | } 47 | 48 | resource "aws_api_gateway_integration" "lambda_integration" { 49 | count = var.with_api_gateway ? 1 : 0 50 | rest_api_id = aws_api_gateway_rest_api.lambda_api[0].id 51 | resource_id = aws_api_gateway_resource.lambda_api_resource[0].id 52 | http_method = aws_api_gateway_method.method[0].http_method 53 | integration_http_method = "POST" 54 | type = "AWS_PROXY" 55 | uri = aws_lambda_function.go_lambda.invoke_arn 56 | } 57 | 58 | resource "aws_lambda_permission" "api_gateway_lambda" { 59 | count = var.with_api_gateway ? 1 : 0 60 | statement_id = "AllowExecutionFromAPIGateway" 61 | action = "lambda:InvokeFunction" 62 | function_name = aws_lambda_function.go_lambda.function_name 63 | principal = "apigateway.amazonaws.com" 64 | source_arn = "arn:aws:execute-api:${var.region}:${data.aws_caller_identity.current.account_id}:${aws_api_gateway_rest_api.lambda_api[0].id}/*" 65 | } 66 | 67 | resource "aws_api_gateway_usage_plan" "lambda_api_usage" { 68 | count = var.with_api_gateway ? 1 : 0 69 | name = "lambda-api-usage" 70 | description = "lambda api usage" 71 | product_code = "LAMBDA_API" 72 | 73 | api_stages { 74 | api_id = aws_api_gateway_rest_api.lambda_api[0].id 75 | stage = aws_api_gateway_stage.lambda_api_stage[0].stage_name 76 | } 77 | 78 | quota_settings { 79 | limit = 10000 80 | offset = 0 81 | period = "DAY" 82 | } 83 | 84 | throttle_settings { 85 | burst_limit = 5 86 | rate_limit = 10 87 | } 88 | } 89 | 90 | resource "aws_api_gateway_api_key" "lambda_api_key" { 91 | count = var.with_api_gateway ? 1 : 0 92 | name = "developer" 93 | } 94 | 95 | resource "aws_api_gateway_usage_plan_key" "lambda_api_key_usage_plan" { 96 | count = var.with_api_gateway ? 1 : 0 97 | key_id = aws_api_gateway_api_key.lambda_api_key[0].id 98 | key_type = "API_KEY" 99 | usage_plan_id = aws_api_gateway_usage_plan.lambda_api_usage[0].id 100 | } 101 | --------------------------------------------------------------------------------