Skip to content

feat: Terraform example #1478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0a25912
#1445 first implementation of terraform core example
Oct 6, 2023
1745a6b
#1445 updated readme to include maven instructions
Oct 6, 2023
03bce9d
Merge pull request #1 from skal111/feat/terraform-examples
skal111 Oct 6, 2023
6fc3428
Merge pull request #2 from aws-powertools/main
skal111 Oct 6, 2023
54d9491
Merge pull request #3 from aws-powertools/main
skal111 Oct 13, 2023
8bf546a
#1458 fixed readme typo + removed lambda env configuration + output a…
Oct 13, 2023
511fae3
#1458 added tflint and tf validate to the PR build
Oct 13, 2023
c5bf093
Merge branch 'main' into main
scottgerring Oct 13, 2023
a93a086
#1458 tf plan, removed tf aws variables, removed xray from AppTest
Oct 13, 2023
10fbe45
Merge branch 'main' of github.com:skal111/powertools-lambda-java
Oct 13, 2023
db01cae
#1458 tentative fix -> tf validate fails without proper AWS credentials
Oct 13, 2023
9019e73
#1458 add LAMBDA_TASK_ROOT at pom level, removed tf plan for now, cha…
Oct 16, 2023
4b83369
#1458 set aws credentials at the github actions level
Oct 16, 2023
2a63ecc
#1445 first implementation of terraform core example
Oct 6, 2023
b2e6f46
#1445 updated readme to include maven instructions
Oct 6, 2023
b843ede
#1458 fixed readme typo + removed lambda env configuration + output a…
Oct 13, 2023
f7a9747
#1458 added tflint and tf validate to the PR build
Oct 13, 2023
53691a9
#1458 tf plan, removed tf aws variables, removed xray from AppTest
Oct 13, 2023
f85f5e5
#1458 tentative fix -> tf validate fails without proper AWS credentials
Oct 13, 2023
86155a9
#1458 add LAMBDA_TASK_ROOT at pom level, removed tf plan for now, cha…
Oct 16, 2023
01bbf80
#1458 set aws credentials at the github actions level
Oct 16, 2023
3f5e20a
#1458 revert to having a simple aws provider configuration
Oct 17, 2023
788119d
Merge branch 'main' of github.com:skal111/powertools-lambda-java
Oct 17, 2023
d944264
#1458 changed transformer
Oct 18, 2023
01e1388
#1458 fixed shade plugin transformer dependency
Oct 18, 2023
c552a5c
Merge branch 'main' into main
jeromevdl Oct 19, 2023
5648cb0
#1458 enabled aws credentials in github action
Oct 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/pr_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ jobs:
env:
JAVA: ${{ matrix.java }}
AWS_REGION: eu-west-1
permissions:
id-token: write # needed to interact with GitHub's OIDC Token endpoint.
contents: read
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Setup java
Expand All @@ -68,6 +71,32 @@ jobs:
run: |
cd examples/powertools-examples-core/gradle
./gradlew build
- name: Setup Terraform
Copy link
Contributor

@jeromevdl jeromevdl Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- name: Setup Terraform
- name: Setup AWS credentials
uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Terraform

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need to add this after the env (line 56)

    permissions:
      id-token: write # needed to interact with GitHub's OIDC Token endpoint.
      contents: read

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, let me try again

if: ${{ matrix.java == '11' }}
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3
- name: Setup AWS credentials
uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }}
aws-region: ${{ env.AWS_REGION }}
- name: Terraform validate
if: ${{ matrix.java == '11' }}
run: |
terraform -version
cd examples/powertools-examples-core/terraform
terraform init -backend=false
terraform validate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we do a plan too ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your call, if you think it adds value to the build.

Copy link
Contributor Author

@skal111 skal111 Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

terraform plan was added but terraform validate fails because there are no AWS credentials available in the CI environment. They are required by terraform AWS provider.
I tried, but was unsuccesful at adding

I can't reproduce this error in my environment so I'm struggling to fix it.

I suggest we simply configure the provider with region = "us-east-1" (or any other region) as it seems to pass

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe because you don't have permission to do that as it's from a fork

terraform plan
- name: Setup Terraform lint
if: ${{ matrix.java == '11' }}
uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1
- name: Terraform lint
if: ${{ matrix.java == '11' }}
run: |
tflint --version
cd examples/powertools-examples-core/terraform
tflint --init
tflint -f compact
- name: Upload coverage to Codecov
uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1
if: ${{ matrix.java == '11' }} # publish results once
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,6 @@ example/HelloWorldFunction/build
/example/.gradle/
/example/.java-version
.gradle
build/
build/
.terraform*
terraform.tfstate*
1 change: 1 addition & 0 deletions examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<module>powertools-examples-core/cdk/app</module>
<module>powertools-examples-core/cdk/infra</module>
<module>powertools-examples-core/serverless</module>
<module>powertools-examples-core/terraform</module>
<module>powertools-examples-idempotency</module>
<module>powertools-examples-parameters</module>
<module>powertools-examples-serialization</module>
Expand Down
1 change: 1 addition & 0 deletions examples/powertools-examples-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ We provide examples for the following infrastructure-as-code tools:
* [AWS SAM](sam/)
* [AWS CDK](cdk/)
* [Serverless framework](serverless/)
* [Terraform](terraform/)

We also provide an example showing the integration of SAM, Powertools, and Gradle:

Expand Down
3 changes: 3 additions & 0 deletions examples/powertools-examples-core/terraform/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
rule "terraform_required_version" {
enabled = false
}
27 changes: 27 additions & 0 deletions examples/powertools-examples-core/terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Powertools for AWS Lambda (Java) - Core Utilities Example with Terraform

This project demonstrates the Lambda for Powertools Java module deployed using [Terraform](https://www.terraform.io/).
For general information on the deployed example itself, you can refer to the parent [README](../README.md).
To install Terraform if you don't have it yet, you can follow the [Install Terraform Guide](https://developer.hashicorp.com/terraform/downloads?product_intent=terraform).

## Configuration
Terraform uses [main.tf](./main.tf) to define the application's AWS resources.
This file defines the Lambda function to be deployed as well as API Gateway for it.

It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests.


## Deploy the sample application

To deploy the app, simply run the following commands:
```bash
terraform init
mvn package && terraform apply
```

## Useful commands

To destroy the app
```bash
terraform destroy
```
94 changes: 94 additions & 0 deletions examples/powertools-examples-core/terraform/infra/api-gateway.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
resource "aws_api_gateway_rest_api" "hello_world_api" {
name = "hello_world_api"
description = "API Gateway endpoint URL for Prod stage for Hello World function"
}

resource "aws_api_gateway_resource" "hello_resource" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
parent_id = "${aws_api_gateway_rest_api.hello_world_api.root_resource_id}"
path_part = "hello"
}

resource "aws_api_gateway_resource" "hello_stream_resource" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
parent_id = "${aws_api_gateway_rest_api.hello_world_api.root_resource_id}"
path_part = "hellostream"
}

resource "aws_api_gateway_method" "hello_get_method" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
resource_id = "${aws_api_gateway_resource.hello_resource.id}"
http_method = "GET"
authorization = "NONE"
}

resource "aws_api_gateway_method" "hello_stream_get_method" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
resource_id = "${aws_api_gateway_resource.hello_stream_resource.id}"
http_method = "GET"
authorization = "NONE"
}

resource "aws_api_gateway_integration" "java_lambda_integration" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
resource_id = "${aws_api_gateway_resource.hello_resource.id}"
http_method = "${aws_api_gateway_method.hello_get_method.http_method}"

integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.hello_world_lambda.invoke_arn}"
}

resource "aws_api_gateway_integration" "java_stream_lambda_integration" {
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
resource_id = "${aws_api_gateway_resource.hello_stream_resource.id}"
http_method = "${aws_api_gateway_method.hello_stream_get_method.http_method}"

integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.hello_world_stream_lambda.invoke_arn}"
}

resource "aws_api_gateway_deployment" "prod_deployment" {
depends_on = [aws_api_gateway_integration.java_lambda_integration, aws_api_gateway_integration.java_stream_lambda_integration]
rest_api_id = "${aws_api_gateway_rest_api.hello_world_api.id}"
stage_name = "prod"
}

# Allows API gateway to invoke lambda
resource "aws_lambda_permission" "hello_world_lambda_invoke" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.hello_world_lambda.function_name}"
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.hello_world_api.execution_arn}/${aws_api_gateway_deployment.prod_deployment.stage_name}/GET/hello"
}

# Allows API gateway to invoke lambda
resource "aws_lambda_permission" "hello_world_lambda_testinvoke" {
statement_id = "AllowAPIGatewayTestInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.hello_world_lambda.function_name}"
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.hello_world_api.execution_arn}/test-invoke-stage/GET/hello"
}

# Allows API gateway to invoke lambda
resource "aws_lambda_permission" "hello_world_stream_lambda_invoke" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.hello_world_stream_lambda.function_name}"
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.hello_world_api.execution_arn}/${aws_api_gateway_deployment.prod_deployment.stage_name}/GET/hellostream"
}

# Allows API gateway to invoke lambda
resource "aws_lambda_permission" "hello_world_stream_lambda_testinvoke" {
statement_id = "AllowAPIGatewayTestInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.hello_world_stream_lambda.function_name}"
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.hello_world_api.execution_arn}/test-invoke-stage/GET/hellostream"
}

output "invoke" {value=aws_api_gateway_deployment.prod_deployment.invoke_url}
95 changes: 95 additions & 0 deletions examples/powertools-examples-core/terraform/infra/lambda.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
resource "aws_lambda_function" "hello_world_lambda" {
runtime = "java11"
filename = "target/helloworld-lambda.jar"
source_code_hash = filebase64sha256("target/helloworld-lambda.jar")
function_name = "hello_world_lambda"

handler = "helloworld.App"
description = "Powertools example, deployed by Terraform"
timeout = 20
memory_size = 512
role = "${aws_iam_role.iam_role_for_lambda.arn}"
tracing_config {
mode = "Active"
}
depends_on = [aws_cloudwatch_log_group.log_group]
}

resource "aws_lambda_function" "hello_world_stream_lambda" {
runtime = "java11"
filename = "target/helloworld-lambda.jar"
source_code_hash = filebase64sha256("target/helloworld-lambda.jar")
function_name = "hello_world_stream_lambda"

handler = "helloworld.AppStream"
description = "Powertools example, deployed by Terraform"
timeout = 20
memory_size = 512
role = "${aws_iam_role.iam_role_for_lambda.arn}"
tracing_config {
mode = "Active"
}
depends_on = [aws_cloudwatch_log_group.log_group]
}

# Create a log group for the lambda
resource "aws_cloudwatch_log_group" "log_group" {
name = "/aws/lambda/hello_world_lambda"
}

# Create a log group for the lambda
resource "aws_cloudwatch_log_group" "log_group_stream" {
name = "/aws/lambda/hello_world_stream_lambda"
}

# lambda role
resource "aws_iam_role" "iam_role_for_lambda" {
name = "lambda-invoke-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

# lambda policy, allow logs to be published to CloudWatch, and traces to Xray
resource "aws_iam_policy" "iam_policy_for_lambda" {
name = "lambda-invoke-policy"
path = "/"

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaPolicy",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"xray:PutTelemetryRecords",
"xray:PutTraceSegments"
],
"Resource": "*"
}
]
}
EOF
}

# Attach the policy to the role
resource "aws_iam_role_policy_attachment" "aws_iam_role_policy_attachment" {
role = "${aws_iam_role.iam_role_for_lambda.name}"
policy_arn = "${aws_iam_policy.iam_policy_for_lambda.arn}"
}
22 changes: 22 additions & 0 deletions examples/powertools-examples-core/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

# terraform modules
module "powertools_for_java_lambda" {
source = "./infra/"
}

output "api_url" {
value = module.powertools_for_java_lambda.invoke
description = "URL where the API gateway can be invoked"
}

# Configure the AWS Provider
provider "aws" {
}
Loading