Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions .github/workflows/commitmsg-conform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Commit Message Conformance

on:
pull_request: {}

permissions:
statuses: write
checks: write
contents: read
pull-requests: read

jobs:
commitmsg-conform:
uses: actionsforge/actions/.github/workflows/commitmsg-conform.yml@main
14 changes: 14 additions & 0 deletions .github/workflows/markdown-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Markdown Lint

on:
pull_request: {}

permissions:
statuses: write
checks: write
contents: read
pull-requests: read

jobs:
markdown-lint:
uses: actionsforge/actions/.github/workflows/markdown-lint.yml@main
13 changes: 13 additions & 0 deletions .github/workflows/terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Generate terraform docs

on:
push:
branches:
- main

permissions:
contents: write

jobs:
terraform-docs:
uses: actionsforge/actions/.github/workflows/terraform-docs.yml@main
13 changes: 13 additions & 0 deletions .github/workflows/terraform-lint-validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Terraform Lint & Validate

on:
pull_request: {}
permissions:
statuses: write
checks: write
contents: read
pull-requests: read

jobs:
terraform-lint-validate:
uses: actionsforge/actions/.github/workflows/terraform-lint-validate.yml@main
12 changes: 12 additions & 0 deletions .github/workflows/terraform-tag-and-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Terraform Tag and Release
on:
workflow_run:
workflows: ["Generate terraform docs"]
types:
- completed

permissions:
contents: write
jobs:
terraform-tag-and-release:
uses: actionsforge/actions/.github/workflows/terraform-tag-and-release.yml@main
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Caller-managed Lambda zip build outputs
**/.build/

# Node.js Lambda examples: install deps locally; do not commit node_modules
examples/**/node_modules/

# Terraform
.terraform/
.terraform.lock.hcl
*.tfstate
*.tfstate.*
*.tfvars
!*.tfvars.example
crash.log
crash.*.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
.terraformrc
terraform.rc
4 changes: 4 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"words": [
]
}
19 changes: 19 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"recommendations": [
"davidanson.vscode-markdownlint",
"eamodio.gitlens",
"esbenp.prettier-vscode",
"foxundermoon.shell-format",
"Gruntfuggly.todo-tree",
"hashicorp.terraform",
"mhutchie.git-graph",
"ms-python.autopep8",
"ms-python.debugpy",
"ms-python.python",
"ms-python.black-formatter",
"ms-python.flake8",
"streetsidesoftware.code-spell-checker",
"usernamehw.errorlens",
"vscode-icons-team.vscode-icons"
]
}
218 changes: 218 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"files.associations": {
"*.dockerfile": "dockerfile",
"*.sh.tpl": "shellscript",
"docker-compose*.yml": "yaml",
"Dockerfile*": "dockerfile",
"*.py.tpl": "python",
"*.yaml.tpl": "yaml",
"*.yml.tpl": "yaml",
"*.tf": "terraform",
"*.tfvars": "terraform"
},
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"__debug_bin": true,
"vendor/": true,
"go.sum": true,
"**/__pycache__": true,
"**/*.pyc": true,
"**/.pytest_cache": true,
"**/.mypy_cache": true,
"**/node_modules": true,
"**/.terraform": true,
"**/.terragrunt-cache": true,
"**/Thumbs.db": true,
"**/.ruff_cache": true,
"**/.coverage": true,
"**/htmlcov": true,
"**/*.tfstate": true,
"**/*.tfstate.*": true
},
"files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true,
"files.eol": "\n",
"remote.extensionKind": {
"ms-azuretools.vscode-docker": "ui",
"ms-vscode-remote.remote-containers": "ui"
},
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.rulers": [79],
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 79,
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.trimAutoWhitespace": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit",
"source.fixAll.ruff": "explicit"
},
"prettier.requireConfig": true,
"workbench.iconTheme": "vscode-icons",
"workbench.colorTheme": "Visual Studio Dark",
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features",
"editor.foldingStrategy": "indentation"
},
"[dockerfile]": {
"editor.defaultFormatter": "ms-azuretools.vscode-docker"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
},
"[json]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[shellscript]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[terraform]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "hashicorp.terraform",
"editor.insertSpaces": true,
"editor.tabSize": 2
},
"[yaml]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.insertSpaces": true,
"editor.tabSize": 2
},
"[yml]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.insertSpaces": true,
"editor.tabSize": 2
},
"[python]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit",
"source.fixAll.ruff": "explicit"
},
"editor.rulers": [79],
"editor.wordWrapColumn": 79,
"editor.tabSize": 4,
"editor.insertSpaces": true
},
"python.formatting.provider": "none",
"python.formatting.blackArgs": [
"--line-length=79",
"--target-version=py39",
"--skip-string-normalization",
"--config=lambdas/pyproject.toml"
],
"python.linting.enabled": true,
"python.linting.lintOnSave": true,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length=79",
"--extend-ignore=E203,W503,E501",
"--max-complexity=10"
],
"ruff.enable": true,
"ruff.fixAll": true,
"ruff.organizeImports": true,
"ruff.lint.enable": true,
"ruff.format.enable": true,
"ruff.codeAction.fixViolation": {
"enable": true
},
"ruff.codeAction.disableRuleComment": {
"enable": true
},
"python.linting.mypyEnabled": true,
"python.linting.mypyArgs": [
"--config-file=lambdas/pyproject.toml"
],
"python.linting.pylintEnabled": false,
"isort.args": [
"--settings-path=lambdas/pyproject.toml"
],
"isort.check": true,
"python.analysis.typeCheckingMode": "off",
"python.analysis.autoImportCompletions": true,
"python.analysis.autoSearchPaths": true,
"python.analysis.diagnosticMode": "workspace",
"python.analysis.completeFunctionParens": true,
"python.analysis.autoFormatStrings": true,
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": [
"lambdas"
],
"python.testing.autoTestDiscoverOnSaveEnabled": true,
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.terminal.activateEnvironment": false,
"autoDocstring.docstringFormat": "google",
"autoDocstring.startOnNewLine": false,
"autoDocstring.includeExtendedSummary": true,
"git.autofetch": true,
"git.confirmSync": false,
"git.enableSmartCommit": true,
"terminal.integrated.defaultProfile.linux": "bash",
"terminal.integrated.copyOnSelection": true,
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/__pycache__": true,
"**/.pytest_cache": true,
"**/.mypy_cache": true,
"**/.ruff_cache": true
},
"markdown.extension.toc.levels": "2..6",
"markdown.extension.print.absoluteImgPath": false,
"yaml.format.enable": true,
"yaml.format.singleQuote": false,
"yaml.format.bracketSpacing": true,
"python.analysis.indexing": true,
"python.analysis.packageIndexDepths": [
{
"name": "boto3",
"depth": 2
},
{
"name": "botocore",
"depth": 2
}
],
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/*/**": true,
"**/__pycache__/**": true,
"**/.pytest_cache/**": true,
"**/.mypy_cache/**": true,
"**/.terraform/**": true,
"**/.terragrunt-cache/**": true
},
"terraform.format.enable": true,
"terraform.lint.enable": true,

"[markdown]": {
"editor.defaultFormatter": "davidanson.vscode-markdownlint",
"editor.formatOnSave": true
},
"markdownlint.config": {
"MD060": {
"style": "any"
}
}
}
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
# terraform-aws-lambda-managed-instance
Terraform module to run AWS Lambda on Managed Instances (EC2-backed) with a capacity provider and VPC config.

Terraform modules and examples for **AWS Lambda Managed Instances (LMI)**—capacity providers in your VPC, functions that run on managed instance capacity, and optional supporting stacks.

## Modules

| Module | Role |
| --- | --- |
| [modules/vpc](modules/vpc/) | VPC with public and private subnets and a single NAT Gateway |
| [modules/lambda_managed_instance](modules/lambda_managed_instance/) | IAM, **CreateCapacityProvider**, and operator wiring for LMI in your subnets and security groups |
| [modules/lambda_managed_function](modules/lambda_managed_function/) | Execution role, log group, and **`aws_lambda_function`** with **`capacity_provider_config`** (publish-on-deploy, optional extra IAM policies) |

Use the modules from your own root module; paths can be local or `git::` (see [Terraform module sources](https://developer.hashicorp.com/terraform/language/modules/sources)).

```hcl
module "vpc" {
source = "tfstack/lambda-managed-instance/aws//modules/vpc"
# ...
}

module "lmi" {
source = ""tfstack/lambda-managed-instance/aws//modules/lambda_managed_instance"
subnet_ids = module.vpc.private_subnet_ids
security_group_ids = [aws_security_group.app.id]
# ...
}
```

## Repository layout

| Path | Purpose |
| --- | --- |
| **Root** (`main.tf`, `variables.tf`, …) | Smoke-test stack: VPC + security group + LMI + sample **Python 3.14** function—used by **`terraform test`** in CI |
| [examples/basic](examples/basic/) | Same stack as root; separate directory and state—see [examples/basic/README.md](examples/basic/README.md) |
| [examples/custom-scaling](examples/custom-scaling/) | Manual scaling mode and instance-type constraints—see [examples/custom-scaling/README.md](examples/custom-scaling/README.md) |
| [examples/waf-loki](examples/waf-loki/) | End-to-end demo: existing WAF log bucket → S3 event → **Node.js 24** LMI function → Loki + Grafana on EC2 behind an ALB—see [examples/waf-loki/README.md](examples/waf-loki/README.md) |
| [tests/stack.tftest.hcl](tests/stack.tftest.hcl) | **`terraform test`** with **`mock_provider "aws"`** (plan-only, no credentials) |

## Examples (summary)

- **Root / basic** — Fastest way to prove LMI in a fresh VPC (two AZs by default).
- **custom-scaling** — Shows **`scaling_mode = "Manual"`** and **`allowed_instance_types`** when you want explicit instance families.
- **waf-loki** — Full walkthrough-style path: S3 notifications, optional **WAFv2** logging to the same bucket, observability on private EC2, Grafana on a CIDR-restricted public ALB. Requires an **existing** S3 bucket, **archive** and **http** providers (declared in that example’s `versions.tf`), and a region where LMI is enabled.

<!-- BEGIN_TF_DOCS -->
<!-- END_TF_DOCS -->
Loading