first claude draft
This commit is contained in:
203
infra/aws/terraform/lambda.tf
Normal file
203
infra/aws/terraform/lambda.tf
Normal file
@@ -0,0 +1,203 @@
|
||||
# Lambda Functions for Data Processing Pipeline
|
||||
# These are optional and enabled via enable_lambda_pipeline variable
|
||||
|
||||
# SQS Queue for buffering metrics
|
||||
resource "aws_sqs_queue" "metrics" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
name = "${var.project_name}-metrics"
|
||||
visibility_timeout_seconds = var.lambda_timeout * 2
|
||||
message_retention_seconds = 86400 # 24 hours
|
||||
|
||||
redrive_policy = jsonencode({
|
||||
deadLetterTargetArn = aws_sqs_queue.metrics_dlq[0].arn
|
||||
maxReceiveCount = 3
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_sqs_queue" "metrics_dlq" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
name = "${var.project_name}-metrics-dlq"
|
||||
message_retention_seconds = 1209600 # 14 days
|
||||
}
|
||||
|
||||
# S3 Bucket for metric backups
|
||||
resource "aws_s3_bucket" "metrics" {
|
||||
count = var.enable_s3_backup ? 1 : 0
|
||||
|
||||
bucket_prefix = "${var.project_name}-metrics-"
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_lifecycle_configuration" "metrics" {
|
||||
count = var.enable_s3_backup ? 1 : 0
|
||||
bucket = aws_s3_bucket.metrics[0].id
|
||||
|
||||
rule {
|
||||
id = "archive-old-metrics"
|
||||
status = "Enabled"
|
||||
|
||||
transition {
|
||||
days = 30
|
||||
storage_class = "STANDARD_IA"
|
||||
}
|
||||
|
||||
transition {
|
||||
days = 90
|
||||
storage_class = "GLACIER"
|
||||
}
|
||||
|
||||
expiration {
|
||||
days = 365
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# IAM Role for Lambda
|
||||
resource "aws_iam_role" "lambda" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
name_prefix = "${var.project_name}-lambda-"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "lambda.amazonaws.com"
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "lambda" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
name = "lambda-policy"
|
||||
role = aws_iam_role.lambda[0].id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
]
|
||||
Resource = "arn:aws:logs:*:*:*"
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"sqs:ReceiveMessage",
|
||||
"sqs:DeleteMessage",
|
||||
"sqs:GetQueueAttributes"
|
||||
]
|
||||
Resource = aws_sqs_queue.metrics[0].arn
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"s3:PutObject",
|
||||
"s3:GetObject"
|
||||
]
|
||||
Resource = var.enable_s3_backup ? "${aws_s3_bucket.metrics[0].arn}/*" : "*"
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
# Lambda function for metric aggregation
|
||||
resource "aws_lambda_function" "aggregator" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
function_name = "${var.project_name}-aggregator"
|
||||
role = aws_iam_role.lambda[0].arn
|
||||
handler = "main.handler"
|
||||
runtime = "python3.11"
|
||||
timeout = var.lambda_timeout
|
||||
memory_size = var.lambda_memory_size
|
||||
|
||||
# Placeholder - will be deployed via CI/CD
|
||||
filename = "${path.module}/../lambdas/aggregator/placeholder.zip"
|
||||
source_code_hash = filebase64sha256("${path.module}/../lambdas/aggregator/placeholder.zip")
|
||||
|
||||
environment {
|
||||
variables = {
|
||||
TIMESCALE_HOST = aws_instance.sysmonstm.private_ip
|
||||
LOG_LEVEL = "INFO"
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [filename, source_code_hash]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lambda_event_source_mapping" "sqs_trigger" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
event_source_arn = aws_sqs_queue.metrics[0].arn
|
||||
function_name = aws_lambda_function.aggregator[0].arn
|
||||
batch_size = 100
|
||||
|
||||
scaling_config {
|
||||
maximum_concurrency = 5
|
||||
}
|
||||
}
|
||||
|
||||
# CloudWatch Event for scheduled compaction
|
||||
resource "aws_cloudwatch_event_rule" "compactor" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
name = "${var.project_name}-compactor-schedule"
|
||||
description = "Trigger metric compaction every hour"
|
||||
schedule_expression = "rate(1 hour)"
|
||||
}
|
||||
|
||||
resource "aws_lambda_function" "compactor" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
function_name = "${var.project_name}-compactor"
|
||||
role = aws_iam_role.lambda[0].arn
|
||||
handler = "main.handler"
|
||||
runtime = "python3.11"
|
||||
timeout = 300
|
||||
memory_size = 512
|
||||
|
||||
filename = "${path.module}/../lambdas/compactor/placeholder.zip"
|
||||
source_code_hash = filebase64sha256("${path.module}/../lambdas/compactor/placeholder.zip")
|
||||
|
||||
environment {
|
||||
variables = {
|
||||
TIMESCALE_HOST = aws_instance.sysmonstm.private_ip
|
||||
S3_BUCKET = var.enable_s3_backup ? aws_s3_bucket.metrics[0].bucket : ""
|
||||
LOG_LEVEL = "INFO"
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [filename, source_code_hash]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_event_target" "compactor" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
rule = aws_cloudwatch_event_rule.compactor[0].name
|
||||
target_id = "compactor-lambda"
|
||||
arn = aws_lambda_function.compactor[0].arn
|
||||
}
|
||||
|
||||
resource "aws_lambda_permission" "compactor_cloudwatch" {
|
||||
count = var.enable_lambda_pipeline ? 1 : 0
|
||||
|
||||
statement_id = "AllowCloudWatchInvoke"
|
||||
action = "lambda:InvokeFunction"
|
||||
function_name = aws_lambda_function.compactor[0].function_name
|
||||
principal = "events.amazonaws.com"
|
||||
source_arn = aws_cloudwatch_event_rule.compactor[0].arn
|
||||
}
|
||||
Reference in New Issue
Block a user