Skip to content

Commit fdf1d90

Browse files
BrandonLWhiteCopilotmoritzzimmer
authored
feat: add pass-through file_system_config variable for EFS support (#181)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Moritz Zimmer <moritzzimmer@users.noreply.github.com>
1 parent 2e61a07 commit fdf1d90

8 files changed

Lines changed: 208 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ see [examples](examples/deployment) for details.
347347
- [deployment](examples/deployment)
348348
- [cloudwatch-logs](examples/cloudwatch-logs)
349349
- [with-cloudwatch-event-rules](examples/with-cloudwatch-event-rules)
350+
- [with-efs](examples/with-efs)
350351
- [with-event-source-mappings](examples/with-event-source-mappings)
351352
- [with-sns-subscriptions](examples/with-sns-subscriptions)
352353
- [with-vpc](examples/with-vpc)
@@ -443,6 +444,7 @@ No modules.
443444
| <a name="input_environment"></a> [environment](#input\_environment) | Environment (e.g. env variables) configuration for the Lambda function enable you to dynamically pass settings to your function code and libraries | <pre>object({<br/> variables = map(string)<br/> })</pre> | `null` | no |
444445
| <a name="input_ephemeral_storage_size"></a> [ephemeral\_storage\_size](#input\_ephemeral\_storage\_size) | The size of your Lambda functions ephemeral storage (/tmp) represented in MB. Valid value between 512 MB to 10240 MB. | `number` | `512` | no |
445446
| <a name="input_event_source_mappings"></a> [event\_source\_mappings](#input\_event\_source\_mappings) | Creates event source mappings to allow the Lambda function to get events from Kinesis, DynamoDB and SQS. The IAM role of this Lambda function will be enhanced with necessary minimum permissions to get those events. | `any` | `{}` | no |
447+
| <a name="input_file_system_config"></a> [file\_system\_config](#input\_file\_system\_config) | Configuration block for EFS file system, `local_mount_path` must start with `/mnt/` | <pre>object({<br/> arn = string<br/> local_mount_path = string<br/> })</pre> | `null` | no |
446448
| <a name="input_filename"></a> [filename](#input\_filename) | The path to the function's deployment package within the local filesystem. If defined, The s3\_-prefixed options and image\_uri cannot be used. | `string` | `null` | no |
447449
| <a name="input_function_name"></a> [function\_name](#input\_function\_name) | A unique name for your Lambda Function. | `string` | n/a | yes |
448450
| <a name="input_handler"></a> [handler](#input\_handler) | The function entrypoint in your code. | `string` | `""` | no |

examples/with-efs/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Example with EFS
2+
3+
Creates an AWS Lambda function connected to an EFS file system via an access point.
4+
5+
## usage
6+
7+
```
8+
terraform init
9+
terraform plan
10+
```
11+
12+
Note that this example may create resources which cost money. Run `terraform destroy` to destroy those resources.
13+
14+
<!-- BEGIN_TF_DOCS -->
15+
## Requirements
16+
17+
| Name | Version |
18+
|------|---------|
19+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
20+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
21+
22+
## Providers
23+
24+
| Name | Version |
25+
|------|---------|
26+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.0 |
27+
28+
## Modules
29+
30+
| Name | Source | Version |
31+
|------|--------|---------|
32+
| <a name="module_fixtures"></a> [fixtures](#module\_fixtures) | ../fixtures | n/a |
33+
| <a name="module_lambda"></a> [lambda](#module\_lambda) | ../../ | n/a |
34+
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
35+
36+
## Resources
37+
38+
| Name | Type |
39+
|------|------|
40+
| [aws_efs_access_point.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_access_point) | resource |
41+
| [aws_efs_file_system.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource |
42+
| [aws_efs_mount_target.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource |
43+
| [aws_security_group.efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
44+
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
45+
46+
## Inputs
47+
48+
| Name | Description | Type | Default | Required |
49+
|------|-------------|------|---------|:--------:|
50+
| <a name="input_region"></a> [region](#input\_region) | n/a | `string` | `"eu-west-1"` | no |
51+
52+
## Outputs
53+
54+
No outputs.
55+
<!-- END_TF_DOCS -->

examples/with-efs/main.tf

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
data "aws_availability_zones" "available" {}
2+
3+
locals {
4+
vpc_cidr = "10.0.0.0/16"
5+
azs = slice(data.aws_availability_zones.available.names, 0, 3)
6+
}
7+
8+
module "fixtures" {
9+
source = "../fixtures"
10+
}
11+
12+
module "vpc" {
13+
source = "terraform-aws-modules/vpc/aws"
14+
version = "~> 5.0"
15+
16+
azs = local.azs
17+
cidr = local.vpc_cidr
18+
name = module.fixtures.output_function_name
19+
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
20+
}
21+
22+
resource "aws_security_group" "efs" {
23+
name = "${module.fixtures.output_function_name}-efs"
24+
vpc_id = module.vpc.vpc_id
25+
26+
ingress {
27+
from_port = 2049
28+
to_port = 2049
29+
protocol = "tcp"
30+
self = true
31+
}
32+
33+
egress {
34+
from_port = 2049
35+
to_port = 2049
36+
protocol = "tcp"
37+
self = true
38+
}
39+
}
40+
41+
resource "aws_efs_file_system" "this" {
42+
creation_token = module.fixtures.output_function_name
43+
encrypted = true
44+
45+
tags = {
46+
Name = module.fixtures.output_function_name
47+
}
48+
}
49+
50+
resource "aws_efs_mount_target" "this" {
51+
count = length(module.vpc.private_subnets)
52+
53+
file_system_id = aws_efs_file_system.this.id
54+
subnet_id = module.vpc.private_subnets[count.index]
55+
security_groups = [aws_security_group.efs.id]
56+
}
57+
58+
resource "aws_efs_access_point" "this" {
59+
file_system_id = aws_efs_file_system.this.id
60+
61+
posix_user {
62+
gid = 1000
63+
uid = 1000
64+
}
65+
66+
root_directory {
67+
path = "/lambda"
68+
69+
creation_info {
70+
owner_gid = 1000
71+
owner_uid = 1000
72+
permissions = "755"
73+
}
74+
}
75+
}
76+
77+
module "lambda" {
78+
source = "../../"
79+
80+
architectures = ["arm64"]
81+
description = "Example AWS Lambda function with EFS file system."
82+
filename = module.fixtures.output_path
83+
function_name = module.fixtures.output_function_name
84+
handler = "index.handler"
85+
memory_size = 128
86+
runtime = "nodejs22.x"
87+
publish = false
88+
snap_start = false
89+
source_code_hash = module.fixtures.output_base64sha256
90+
timeout = 30
91+
92+
file_system_config = {
93+
arn = aws_efs_access_point.this.arn
94+
local_mount_path = "/mnt/efs"
95+
}
96+
97+
vpc_config = {
98+
security_group_ids = [aws_security_group.efs.id]
99+
subnet_ids = module.vpc.private_subnets
100+
}
101+
102+
// EFS mount targets must be in available state before Lambda can use them
103+
depends_on = [aws_efs_mount_target.this]
104+
}

examples/with-efs/provider.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
provider "aws" {
2+
region = var.region
3+
4+
skip_credentials_validation = true
5+
skip_metadata_api_check = true
6+
skip_region_validation = true
7+
8+
}

examples/with-efs/variables.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
variable "region" {
2+
default = "eu-west-1"
3+
type = string
4+
}

examples/with-efs/versions.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.5.7"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 6.0"
8+
}
9+
}
10+
}

main.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ resource "aws_lambda_function" "lambda" {
4545
}
4646
}
4747

48+
dynamic "file_system_config" {
49+
for_each = var.file_system_config == null ? [] : [var.file_system_config]
50+
content {
51+
arn = file_system_config.value.arn
52+
local_mount_path = file_system_config.value.local_mount_path
53+
}
54+
}
55+
4856
dynamic "image_config" {
4957
for_each = length(var.image_config) > 0 ? [true] : []
5058
content {
@@ -135,6 +143,14 @@ resource "aws_lambda_function" "lambda_external_lifecycle" {
135143
}
136144
}
137145

146+
dynamic "file_system_config" {
147+
for_each = var.file_system_config == null ? [] : [var.file_system_config]
148+
content {
149+
arn = file_system_config.value.arn
150+
local_mount_path = file_system_config.value.local_mount_path
151+
}
152+
}
153+
138154
dynamic "image_config" {
139155
for_each = length(var.image_config) > 0 ? [true] : []
140156
content {

variables.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ variable "event_source_mappings" {
101101
type = any
102102
}
103103

104+
variable "file_system_config" {
105+
description = "Configuration block for EFS file system, `local_mount_path` must start with `/mnt/`"
106+
default = null
107+
type = object({
108+
arn = string
109+
local_mount_path = string
110+
})
111+
}
112+
104113
variable "filename" {
105114
description = "The path to the function's deployment package within the local filesystem. If defined, The s3_-prefixed options and image_uri cannot be used."
106115
default = null

0 commit comments

Comments
 (0)