Skip to content

Commit 2a5ace0

Browse files
authored
Merge pull request #20 from highwingio/ianbender/pt-62-remove-legacy-broker-suite-terraform-code
Updating to meet current lambda config
2 parents 119b1bc + 8b3fb24 commit 2a5ace0

File tree

8 files changed

+195
-316
lines changed

8 files changed

+195
-316
lines changed

.github/workflows/checks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- uses: actions/checkout@master
1111
- uses: hashicorp/setup-terraform@v1
1212
with:
13-
terraform_version: 1.3.0
13+
terraform_version: 1.7.4
1414
- id: Init
1515
run: terraform init -no-color
1616
- id: Fmt

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
terraform 1.7.4

README.md

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,52 +32,48 @@ No requirements.
3232

3333
## Modules
3434

35-
No modules.
35+
| Name | Source | Version |
36+
|------|--------|---------|
37+
| <a name="module_lambda_function"></a> [lambda\_function](#module\_lambda\_function) | terraform-aws-modules/lambda/aws | 7.2.6 |
3638

3739
## Resources
3840

3941
| Name | Type |
4042
|------|------|
41-
| [aws_cloudwatch_log_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
42-
| [aws_cloudwatch_metric_alarm.lambda_errors](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource |
43-
| [aws_iam_role_policy_attachment.lambda_basic_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
44-
| [aws_iam_role_policy_attachment.lambda_insights](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
45-
| [aws_iam_role_policy_attachment.lambda_networking](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
46-
| [aws_iam_role_policy_attachment.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
47-
| [aws_lambda_function.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
48-
| [aws_s3_bucket_object.lambda_deploy_object](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_object) | resource |
49-
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
43+
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
44+
| [aws_sns_topic.notifications](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/sns_topic) | data source |
45+
| [aws_ssm_parameter.account_name](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
5046
| [aws_ssm_parameter.deployment_bucket_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
47+
| [aws_ssm_parameter.global_account_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
48+
| [aws_ssm_parameter.kms_key_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
5149

5250
## Inputs
5351

5452
| Name | Description | Type | Default | Required |
5553
|------|-------------|------|---------|:--------:|
56-
| <a name="input_deployment_bucket_id"></a> [deployment\_bucket\_id](#input\_deployment\_bucket\_id) | ID of S3 bucket that should store our deployment artifacts. Will use the /account/DEPLOYMENT\_BUCKET\_ID value from SSM unless specified otherwise. | `string` | `null` | no |
57-
| <a name="input_description"></a> [description](#input\_description) | Description of the Lambda Function | `string` | `null` | no |
58-
| <a name="input_environment"></a> [environment](#input\_environment) | Environment variables to be passed to the function | `map(string)` | `{}` | no |
59-
| <a name="input_error_rate_alarm_threshold"></a> [error\_rate\_alarm\_threshold](#input\_error\_rate\_alarm\_threshold) | Error rate (in percent, 1-100) at which to trigger an alarm notification | `number` | `25` | no |
60-
| <a name="input_git_sha"></a> [git\_sha](#input\_git\_sha) | Hash generated by `git hash-object` in source repo and used to determine whether a lambda needs to be updated | `string` | `null` | no |
61-
| <a name="input_handler"></a> [handler](#input\_handler) | Name of the handler function inside the artifact (https://docs.aws.amazon.com/lambda/latest/dg/configuration-console.html) | `string` | n/a | yes |
62-
| <a name="input_layer_arns"></a> [layer\_arns](#input\_layer\_arns) | List of ARNs for layers to use with the function | `list(string)` | `[]` | no |
63-
| <a name="input_log_retention_in_days"></a> [log\_retention\_in\_days](#input\_log\_retention\_in\_days) | Number of days to keep function logs in Cloudwatch | `number` | `365` | no |
64-
| <a name="input_memory_size"></a> [memory\_size](#input\_memory\_size) | Amount of memory (in MB) to allocate to the function | `number` | `128` | no |
65-
| <a name="input_name"></a> [name](#input\_name) | Name for the function | `string` | n/a | yes |
66-
| <a name="input_notifications_topic_arn"></a> [notifications\_topic\_arn](#input\_notifications\_topic\_arn) | SNS topic to send error notifications | `string` | n/a | yes |
67-
| <a name="input_path"></a> [path](#input\_path) | Local path to a zipped artifact containing the function code | `string` | n/a | yes |
68-
| <a name="input_reserved_concurrent_executions"></a> [reserved\_concurrent\_executions](#input\_reserved\_concurrent\_executions) | Reserved concurrent executions (none by default) | `number` | `null` | no |
69-
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Name of the execution role for the function. It does not need to include logging/networking permissions - those policies will be added automatically. | `string` | n/a | yes |
70-
| <a name="input_runtime"></a> [runtime](#input\_runtime) | Language runtime for the function (https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) | `string` | n/a | yes |
71-
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | Security groups for the function (if run in a VPC) | `list(string)` | `[]` | no |
72-
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | Subnets for the function (if run in a VPC) | `list(string)` | `[]` | no |
73-
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to created resources | `map(any)` | `{}` | no |
74-
| <a name="input_timeout"></a> [timeout](#input\_timeout) | Function timeout in seconds | `number` | `15` | no |
54+
| <a name="input_allowed_triggers"></a> [allowed\_triggers](#input\_allowed\_triggers) | n/a | `map(any)` | `{}` | no |
55+
| <a name="input_description"></a> [description](#input\_description) | n/a | `string` | `null` | no |
56+
| <a name="input_ecr_address"></a> [ecr\_address](#input\_ecr\_address) | n/a | `string` | n/a | yes |
57+
| <a name="input_ecr_arn"></a> [ecr\_arn](#input\_ecr\_arn) | n/a | `string` | n/a | yes |
58+
| <a name="input_engine_name"></a> [engine\_name](#input\_engine\_name) | n/a | `string` | n/a | yes |
59+
| <a name="input_environment_variables"></a> [environment\_variables](#input\_environment\_variables) | n/a | `map(any)` | `{}` | no |
60+
| <a name="input_event_source_mapping"></a> [event\_source\_mapping](#input\_event\_source\_mapping) | Map of event source mappings | `map(any)` | `{}` | no |
61+
| <a name="input_function_name"></a> [function\_name](#input\_function\_name) | n/a | `string` | n/a | yes |
62+
| <a name="input_handler"></a> [handler](#input\_handler) | n/a | `string` | `null` | no |
63+
| <a name="input_image_tag"></a> [image\_tag](#input\_image\_tag) | n/a | `string` | `"latest"` | no |
64+
| <a name="input_memory_size"></a> [memory\_size](#input\_memory\_size) | n/a | `number` | `1024` | no |
65+
| <a name="input_policy_statements"></a> [policy\_statements](#input\_policy\_statements) | n/a | `map(any)` | `{}` | no |
66+
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | n/a | `list(string)` | `[]` | no |
67+
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | n/a | `list(string)` | `[]` | no |
68+
| <a name="input_timeout"></a> [timeout](#input\_timeout) | n/a | `string` | `"60"` | no |
7569

7670
## Outputs
7771

7872
| Name | Description |
7973
|------|-------------|
80-
| <a name="output_function_arn"></a> [function\_arn](#output\_function\_arn) | ARN of the created/updated Lambda function |
81-
| <a name="output_function_invoke_arn"></a> [function\_invoke\_arn](#output\_function\_invoke\_arn) | ARN for invoking the created Lambda function |
82-
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | Name of the created Lambda function |
83-
| <a name="output_function_version"></a> [function\_version](#output\_function\_version) | Version of the created/updated Lambda function |
74+
| <a name="output_function_arn"></a> [function\_arn](#output\_function\_arn) | n/a |
75+
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | n/a |
76+
| <a name="output_function_version"></a> [function\_version](#output\_function\_version) | n/a |
77+
| <a name="output_lambda_role_arn"></a> [lambda\_role\_arn](#output\_lambda\_role\_arn) | n/a |
78+
| <a name="output_lambda_role_name"></a> [lambda\_role\_name](#output\_lambda\_role\_name) | n/a |
79+
| <a name="output_qualified_function_arn"></a> [qualified\_function\_arn](#output\_qualified\_function\_arn) | n/a |

data.tf

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1-
data "aws_caller_identity" "current" {}
1+
data "aws_region" "current" {}
2+
3+
data "aws_ssm_parameter" "account_name" {
4+
name = "/account/name"
5+
}
6+
7+
data "aws_sns_topic" "notifications" {
8+
name = "account-notifications"
9+
}
210

311
data "aws_ssm_parameter" "deployment_bucket_id" {
412
name = "/account/DEPLOYMENT_BUCKET_ID"
513
}
14+
15+
data "aws_ssm_parameter" "kms_key_arn" {
16+
name = "/account/KMS_KEY_ARN"
17+
}
18+
19+
data "aws_ssm_parameter" "global_account_id" {
20+
name = "/global/account_id"
21+
}

main.tf

Lines changed: 61 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -23,166 +23,73 @@
2323
*/
2424

2525
locals {
26-
deploy_artifact_key = "deploy.zip"
27-
deployment_bucket_id = coalesce(var.deployment_bucket_id, data.aws_ssm_parameter.deployment_bucket_id.value)
28-
source_hash = coalesce(var.git_sha, try(filebase64sha256(var.path), null))
29-
role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.role_name}"
26+
description = coalesce(var.description, "Highwing Engine - ${title(var.engine_name)}")
27+
handler = coalesce(var.handler, "engines/${var.engine_name}/lambda.handler")
28+
29+
environment = data.aws_ssm_parameter.account_name.value
30+
environment_variables = (
31+
startswith(local.environment, "production")
32+
? var.environment_variables
33+
: merge(var.environment_variables, {
34+
DEV_MODE_ENABLED = true
35+
})
36+
)
3037
}
3138

32-
# Configure default role permissions
33-
resource "aws_iam_role_policy_attachment" "lambda_basic_execution" {
34-
role = var.role_name
35-
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
36-
}
37-
38-
resource "aws_iam_role_policy_attachment" "lambda_networking" {
39-
role = var.role_name
40-
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
41-
}
42-
43-
resource "aws_iam_role_policy_attachment" "lambda_xray" {
44-
role = var.role_name
45-
policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
46-
}
47-
48-
resource "aws_iam_role_policy_attachment" "lambda_insights" {
49-
role = var.role_name
50-
policy_arn = "arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy"
51-
}
52-
53-
# S3 object to hold the deployed artifact
54-
resource "aws_s3_bucket_object" "lambda_deploy_object" {
55-
count = var.image_uri == null ? 1 : 0
56-
bucket = local.deployment_bucket_id
57-
key = "${var.name}/${local.deploy_artifact_key}"
58-
source = var.path
59-
source_hash = md5(local.source_hash)
60-
tags = merge(var.tags, {
61-
GitSHA = var.git_sha
62-
})
63-
}
64-
65-
# The Lambda function itself
66-
resource "aws_lambda_function" "lambda" {
67-
function_name = var.name
68-
description = var.description
69-
handler = var.handler
70-
layers = var.image_uri == null ? concat(
71-
var.layer_arns,
72-
["arn:aws:lambda:us-east-1:580247275435:layer:LambdaInsightsExtension:14"] # ARN for us-east-1
73-
) : null
74-
memory_size = var.memory_size
75-
publish = true
76-
reserved_concurrent_executions = var.reserved_concurrent_executions
77-
role = local.role_arn
78-
runtime = var.runtime
79-
package_type = var.image_uri == null ? "Zip" : "Image"
80-
s3_bucket = var.image_uri == null ? local.deployment_bucket_id : null
81-
s3_key = var.image_uri == null ? aws_s3_bucket_object.lambda_deploy_object[0].key : null
82-
s3_object_version = var.image_uri == null ? aws_s3_bucket_object.lambda_deploy_object[0].version_id : null
83-
image_uri = var.image_uri
84-
tags = var.tags
85-
timeout = var.timeout
86-
87-
dynamic "vpc_config" {
88-
for_each = length(var.subnet_ids) > 0 ? [1] : []
89-
content {
90-
subnet_ids = var.subnet_ids
91-
security_group_ids = var.security_group_ids
92-
}
93-
}
94-
95-
dynamic "environment" {
96-
for_each = length(var.environment) > 0 ? [1] : []
97-
content {
98-
variables = var.environment
99-
}
100-
}
101-
102-
tracing_config {
103-
mode = "Active"
104-
}
105-
106-
lifecycle {
107-
precondition {
108-
condition = (var.image_uri != null && var.path == null) || (var.image_uri == null && var.path != null)
109-
error_message = "Cannot specify image_uri AND path"
39+
module "lambda_function" {
40+
source = "terraform-aws-modules/lambda/aws"
41+
version = "7.2.6"
42+
43+
function_name = var.function_name
44+
description = local.description
45+
handler = local.handler
46+
memory_size = var.memory_size
47+
publish = true
48+
timeout = var.timeout
49+
50+
vpc_subnet_ids = var.subnet_ids
51+
vpc_security_group_ids = var.security_group_ids
52+
53+
attach_cloudwatch_logs_policy = true
54+
attach_dead_letter_policy = true
55+
attach_network_policy = true
56+
attach_tracing_policy = true
57+
58+
allowed_triggers = var.allowed_triggers
59+
60+
number_of_policies = 2
61+
policies = [
62+
"arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy",
63+
"arn:aws:iam::aws:policy/service-role/AWSLambdaSQSQueueExecutionRole"
64+
]
65+
attach_policies = true
66+
67+
attach_policy_statements = length(var.policy_statements) > 0 ? true : false
68+
policy_statements = merge(var.policy_statements, {
69+
ecr = {
70+
effect = "Allow"
71+
actions = [
72+
"ecr:BatchGetImage",
73+
"ecr:GetDownloadUrlForLayer"
74+
]
75+
resources = [var.ecr_arn]
11076
}
111-
precondition {
112-
condition = (var.image_uri != null && var.handler == null) || (var.image_uri == null && var.handler != null)
113-
error_message = "Cannot specify image_uri AND handler"
114-
}
115-
precondition {
116-
condition = (var.image_uri != null && length(var.layer_arns) == 0) || (var.image_uri == null)
117-
error_message = "Cannot specify image_uri AND layer_arns"
118-
}
119-
precondition {
120-
condition = (var.image_uri != null && var.path == null) || (var.image_uri == null && var.path != null)
121-
error_message = "Cannot specify image_uri AND path"
122-
}
123-
precondition {
124-
condition = (var.image_uri != null && var.runtime == null) || (var.image_uri == null && var.path != null)
125-
error_message = "Cannot specify image_uri AND runtime"
126-
}
127-
}
128-
129-
}
130-
131-
# An alarm to notify of function errors
132-
resource "aws_cloudwatch_metric_alarm" "lambda_errors" {
133-
alarm_actions = [var.notifications_topic_arn]
134-
alarm_description = "This metric monitors the error rate on the ${var.name} lambda"
135-
alarm_name = "${var.name} - High Error Rate"
136-
comparison_operator = "GreaterThanOrEqualToThreshold"
137-
evaluation_periods = "2"
138-
threshold = var.error_rate_alarm_threshold
139-
treat_missing_data = "notBreaching"
140-
141-
metric_query {
142-
id = "error_rate"
143-
expression = "errors/invocations*100"
144-
label = "Error Rate"
145-
return_data = "true"
146-
}
147-
148-
metric_query {
149-
id = "errors"
150-
151-
metric {
152-
metric_name = "Errors"
153-
namespace = "AWS/Lambda"
154-
period = "600"
155-
stat = "Sum"
156-
unit = "Count"
157-
158-
dimensions = {
159-
FunctionName = aws_lambda_function.lambda.function_name
160-
}
161-
}
162-
}
77+
})
16378

164-
metric_query {
165-
id = "invocations"
79+
cloudwatch_logs_retention_in_days = 1096
80+
dead_letter_target_arn = data.aws_sns_topic.notifications.arn
81+
kms_key_arn = data.aws_ssm_parameter.kms_key_arn.value
82+
tracing_mode = "Active"
16683

167-
metric {
168-
metric_name = "Invocations"
169-
namespace = "AWS/Lambda"
170-
period = "600"
171-
stat = "Sum"
172-
unit = "Count"
84+
create_package = false
85+
image_uri = "${var.ecr_address}:lambda_${var.image_tag}"
86+
package_type = "Image"
87+
architectures = ["x86_64"]
17388

174-
dimensions = {
175-
FunctionName = aws_lambda_function.lambda.function_name
176-
}
177-
}
178-
}
89+
event_source_mapping = var.event_source_mapping
17990

180-
tags = var.tags
91+
environment_variables = merge(local.environment_variables, {
92+
DD_SERVICE = replace(var.function_name, "-", "_")
93+
})
18194
}
18295

183-
# Configure logging in Cloudwatch
184-
resource "aws_cloudwatch_log_group" "lambda" {
185-
name = "/aws/lambda/${var.name}"
186-
retention_in_days = var.log_retention_in_days
187-
tags = var.tags
188-
}

outputs.tf

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
output "function_name" {
2-
description = "Name of the created Lambda function"
3-
value = aws_lambda_function.lambda.function_name
1+
output "function_arn" {
2+
value = module.lambda_function.lambda_function_arn
43
}
54

6-
output "function_arn" {
7-
description = "ARN of the created/updated Lambda function"
8-
value = aws_lambda_function.lambda.arn
5+
output "qualified_function_arn" {
6+
value = module.lambda_function.lambda_function_qualified_arn
7+
}
8+
9+
output "function_name" {
10+
value = module.lambda_function.lambda_function_name
911
}
1012

1113
output "function_version" {
12-
description = "Version of the created/updated Lambda function"
13-
value = aws_lambda_function.lambda.version
14+
value = module.lambda_function.lambda_function_version
15+
}
16+
17+
output "lambda_role_arn" {
18+
value = module.lambda_function.lambda_role_arn
1419
}
1520

16-
output "function_invoke_arn" {
17-
description = "ARN for invoking the created Lambda function"
18-
value = aws_lambda_function.lambda.invoke_arn
21+
output "lambda_role_name" {
22+
value = module.lambda_function.lambda_role_name
1923
}

0 commit comments

Comments
 (0)