Skip to content

Commit 9ed5413

Browse files
authored
Merge pull request #6 from Jno21/feat/region
feat: add support for multi region using new region field from aws provider v6
2 parents 51afd18 + 746934b commit 9ed5413

6 files changed

Lines changed: 108 additions & 32 deletions

File tree

README.md

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ For complete usage examples demonstrating different configuration scenarios, see
4545
- `dd_api_key_secret_arn` - ARN of existing Secrets Manager secret containing the API key
4646
- `dd_api_key_ssm_parameter_name` - Name of SSM Parameter containing the API key
4747

48+
### AWS Configuration
49+
| Name | Description | Type | Default |
50+
|------|-------------|------|---------|
51+
| region | AWS region to deploy the Datadog Forwarder to. If empty, the forwarder will be deployed to the region set by the provider. | `string` | `null` |
52+
4853
### Lambda Configuration
4954

5055
| Name | Description | Type | Default |
@@ -201,30 +206,27 @@ When deploying the forwarder across multiple AWS regions, you have two options:
201206
The simplest approach is to let the module create all resources in each region:
202207

203208
```hcl
209+
provider "aws" {
210+
region = "us-east-1"
211+
}
212+
204213
# us-east-1 deployment
205214
module "datadog_forwarder_us_east_1" {
206215
source = "path/to/this/module"
207216
208217
function_name = "DatadogForwarder"
209218
dd_api_key = var.datadog_api_key
210219
dd_site = "datadoghq.com"
211-
212-
providers = {
213-
aws = aws.us_east_1
214-
}
215220
}
216221
217222
# us-west-2 deployment
218223
module "datadog_forwarder_us_west_2" {
219224
source = "path/to/this/module"
225+
region = "us-west-2"
220226
221227
function_name = "DatadogForwarder"
222228
dd_api_key = var.datadog_api_key
223229
dd_site = "datadoghq.com"
224-
225-
providers = {
226-
aws = aws.us_west_2
227-
}
228230
}
229231
```
230232

@@ -235,30 +237,27 @@ The module automatically includes the region in IAM resource names to prevent gl
235237
For advanced use cases where you want to manage IAM roles centrally, you must provide **all** external resources to avoid cross-region conflicts:
236238

237239
```hcl
240+
provider "aws" {
241+
region = "us-east-1"
242+
}
243+
238244
module "datadog_forwarder_us_east_1" {
239245
source = "path/to/this/module"
240246
241247
function_name = "DatadogForwarder"
242248
existing_iam_role_arn = "arn:aws:iam::123456789012:role/DatadogForwarderRole"
243249
dd_forwarder_existing_bucket_name = "my-global-datadog-bucket"
244250
dd_api_key_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:datadog-api-key-abc123"
245-
246-
providers = {
247-
aws = aws.us_east_1
248-
}
249251
}
250252
251253
module "datadog_forwarder_us_west_2" {
252254
source = "path/to/this/module"
255+
region = "us-west-2"
253256
254257
function_name = "DatadogForwarder"
255258
existing_iam_role_arn = "arn:aws:iam::123456789012:role/DatadogForwarderRole"
256259
dd_forwarder_existing_bucket_name = "my-global-datadog-bucket"
257260
dd_api_key_secret_arn = "arn:aws:secretsmanager:us-west-2:123456789012:secret:datadog-api-key-def456"
258-
259-
providers = {
260-
aws = aws.us_west_2
261-
}
262261
}
263262
```
264263

data.tf

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ locals {
2121
# Determine if we need to create an S3 bucket for caching and failed events storage
2222
create_s3_bucket = (coalesce(var.dd_fetch_log_group_tags, false) || coalesce(var.dd_fetch_lambda_tags, false) || coalesce(var.dd_fetch_s3_tags, false) || coalesce(var.dd_store_failed_events, false)) && var.dd_forwarder_existing_bucket_name == null
2323

24-
# Default layer ARN based on partition and region
25-
default_layer_arn = "arn:${data.aws_partition.current.partition}:lambda:${data.aws_region.current.region}:${local.dd_account_id}:layer:Datadog-Forwarder:${local.layer_version}"
26-
2724
# Account ID varies by partition
2825
dd_account_id = data.aws_partition.current.partition == "aws-us-gov" ? "002406178527" : "464622532012"
2926

@@ -32,4 +29,11 @@ locals {
3229

3330
# IAM role ARN - use module output if created, otherwise use provided ARN
3431
iam_role_arn = var.existing_iam_role_arn == null ? module.iam[0].iam_role_arn : var.existing_iam_role_arn
32+
33+
# AWS Region
34+
region = coalesce(var.region, data.aws_region.current.region)
35+
36+
# Default layer ARN based on partition and region
37+
default_layer_arn = "arn:${data.aws_partition.current.partition}:lambda:${local.region}:${local.dd_account_id}:layer:Datadog-Forwarder:${local.layer_version}"
38+
3539
}

examples/multi-region/main.tf

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ terraform {
1010
}
1111

1212
provider "aws" {
13-
alias = "us_east_1"
1413
region = "us-east-1"
1514
}
16-
provider "aws" {
17-
alias = "us_east_2"
18-
region = "us-east-2"
19-
}
2015

16+
# The region is not specified, so it will default to us-east-1
2117
module "datadog_forwarder_us_east_1" {
2218
source = "../../"
2319

@@ -36,13 +32,14 @@ module "datadog_forwarder_us_east_1" {
3632
terraform = "true"
3733
dd_forwarder_name = var.function_name
3834
}
39-
providers = {
40-
aws = aws.us_east_1
41-
}
4235
}
36+
4337
module "datadog_forwarder_us_east_2" {
4438
source = "../../"
4539

40+
# Specify the region
41+
region = "us-east-2"
42+
4643
# Required - API key will be stored in Secrets Manager
4744
# Alternatively, use dd_api_key_secret_arn to reference an existing Secrets Manager secret
4845
# Or use dd_api_key_ssm_parameter_name to reference an existing SSM Parameter
@@ -58,7 +55,4 @@ module "datadog_forwarder_us_east_2" {
5855
terraform = "true"
5956
dd_forwarder_name = var.function_name
6057
}
61-
providers = {
62-
aws = aws.us_east_2
63-
}
6458
}

main.tf

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module "iam" {
88
iam_role_path = var.iam_role_path
99
permissions_boundary_arn = var.permissions_boundary_arn
1010
partition = data.aws_partition.current.partition
11-
region = data.aws_region.current.region
11+
region = local.region
1212
tags = var.tags
1313
s3_bucket_permissions = var.dd_forwarder_existing_bucket_name != null || local.create_s3_bucket
1414
forwarder_bucket_arn = local.create_s3_bucket ? aws_s3_bucket.forwarder_bucket[0].arn : null
@@ -27,6 +27,8 @@ module "iam" {
2727
resource "aws_secretsmanager_secret" "dd_api_key_secret" {
2828
count = var.dd_api_key_secret_arn == null && var.dd_api_key_ssm_parameter_name == null ? 1 : 0
2929

30+
region = local.region
31+
3032
name_prefix = "DatadogAPIKey-${var.function_name}"
3133

3234
description = "Datadog API Key"
@@ -37,6 +39,8 @@ resource "aws_secretsmanager_secret" "dd_api_key_secret" {
3739
resource "aws_secretsmanager_secret_version" "dd_api_key_secret_version" {
3840
count = var.dd_api_key_secret_arn == null && var.dd_api_key_ssm_parameter_name == null ? 1 : 0
3941

42+
region = local.region
43+
4044
secret_id = aws_secretsmanager_secret.dd_api_key_secret[0].id
4145
secret_string = var.dd_api_key
4246
}
@@ -45,6 +49,8 @@ resource "aws_secretsmanager_secret_version" "dd_api_key_secret_version" {
4549
resource "aws_s3_bucket" "forwarder_bucket" {
4650
count = local.create_s3_bucket ? 1 : 0
4751

52+
region = local.region
53+
4854
bucket = var.dd_forwarder_bucket_name != null ? var.dd_forwarder_bucket_name : null
4955

5056
force_destroy = true
@@ -55,6 +61,8 @@ resource "aws_s3_bucket" "forwarder_bucket" {
5561
resource "aws_s3_bucket_server_side_encryption_configuration" "forwarder_bucket_encryption" {
5662
count = local.create_s3_bucket ? 1 : 0
5763

64+
region = local.region
65+
5866
bucket = aws_s3_bucket.forwarder_bucket[0].id
5967

6068
rule {
@@ -68,6 +76,8 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "forwarder_bucket_
6876
resource "aws_s3_bucket_public_access_block" "forwarder_bucket_pab" {
6977
count = local.create_s3_bucket ? 1 : 0
7078

79+
region = local.region
80+
7181
bucket = aws_s3_bucket.forwarder_bucket[0].id
7282

7383
block_public_acls = true
@@ -79,6 +89,8 @@ resource "aws_s3_bucket_public_access_block" "forwarder_bucket_pab" {
7989
resource "aws_s3_bucket_logging" "forwarder_bucket_logging" {
8090
count = var.dd_forwarder_buckets_access_logs_target != null ? 1 : 0
8191

92+
region = local.region
93+
8294
bucket = aws_s3_bucket.forwarder_bucket[0].id
8395

8496
target_bucket = var.dd_forwarder_buckets_access_logs_target
@@ -88,6 +100,8 @@ resource "aws_s3_bucket_logging" "forwarder_bucket_logging" {
88100
resource "aws_s3_bucket_lifecycle_configuration" "forwarder_bucket_lifecycle" {
89101
count = local.create_s3_bucket ? 1 : 0
90102

103+
region = local.region
104+
91105
bucket = aws_s3_bucket.forwarder_bucket[0].id
92106

93107
rule {
@@ -108,6 +122,8 @@ resource "aws_s3_bucket_lifecycle_configuration" "forwarder_bucket_lifecycle" {
108122
resource "aws_s3_bucket_policy" "forwarder_bucket_policy" {
109123
count = local.create_s3_bucket ? 1 : 0
110124

125+
region = local.region
126+
111127
bucket = aws_s3_bucket.forwarder_bucket[0].id
112128

113129
policy = jsonencode({
@@ -134,6 +150,7 @@ resource "aws_s3_bucket_policy" "forwarder_bucket_policy" {
134150

135151
# Lambda function
136152
resource "aws_lambda_function" "forwarder" {
153+
region = local.region
137154

138155
function_name = var.function_name
139156
description = "Pushes logs, metrics and traces from AWS to Datadog."
@@ -222,15 +239,19 @@ resource "aws_lambda_function" "forwarder" {
222239

223240
# Lambda permissions
224241
resource "aws_lambda_permission" "cloudwatch_logs_invoke" {
242+
region = local.region
243+
225244
statement_id = "CloudWatchLogsInvokePermission"
226245
action = "lambda:InvokeFunction"
227246
function_name = aws_lambda_function.forwarder.function_name
228247
principal = data.aws_partition.current.partition == "aws-cn" ? "logs.amazonaws.com.cn" : "logs.amazonaws.com"
229248
source_account = data.aws_caller_identity.current.account_id
230-
source_arn = "arn:${data.aws_partition.current.partition}:logs:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:log-group:*:*"
249+
source_arn = "arn:${data.aws_partition.current.partition}:logs:${local.region}:${data.aws_caller_identity.current.account_id}:log-group:*:*"
231250
}
232251

233252
resource "aws_lambda_permission" "s3_invoke" {
253+
region = local.region
254+
234255
statement_id = "S3Permission"
235256
action = "lambda:InvokeFunction"
236257
function_name = aws_lambda_function.forwarder.function_name
@@ -239,6 +260,8 @@ resource "aws_lambda_permission" "s3_invoke" {
239260
}
240261

241262
resource "aws_lambda_permission" "sns_invoke" {
263+
region = local.region
264+
242265
statement_id = "SNSPermission"
243266
action = "lambda:InvokeFunction"
244267
function_name = aws_lambda_function.forwarder.function_name
@@ -247,6 +270,8 @@ resource "aws_lambda_permission" "sns_invoke" {
247270
}
248271

249272
resource "aws_lambda_permission" "eventbridge_invoke" {
273+
region = local.region
274+
250275
statement_id = "CloudWatchEventsPermission"
251276
action = "lambda:InvokeFunction"
252277
function_name = aws_lambda_function.forwarder.function_name
@@ -256,6 +281,8 @@ resource "aws_lambda_permission" "eventbridge_invoke" {
256281

257282
# CloudWatch Log Group
258283
resource "aws_cloudwatch_log_group" "forwarder_log_group" {
284+
region = local.region
285+
259286
name = "/aws/lambda/${aws_lambda_function.forwarder.function_name}"
260287
retention_in_days = var.log_retention_in_days
261288

tests/multi_region.tftest.hcl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Test multi-region support
2+
provider "aws" {
3+
region = "us-east-1"
4+
}
5+
6+
variables {
7+
dd_api_key = "test-api-key-value"
8+
dd_site = "datadoghq.com"
9+
}
10+
11+
run "multi_region_us_east_1" {
12+
command = plan
13+
14+
# Test default region is set to the provider region (us-east-1)
15+
assert {
16+
condition = local.region == "us-east-1"
17+
error_message = "The region should be us-east-1"
18+
}
19+
}
20+
21+
run "multi_region_us_east_2" {
22+
command = plan
23+
24+
variables {
25+
region = "us-east-2"
26+
}
27+
28+
# Test that the region is overridden to us-east-2
29+
assert {
30+
condition = local.region == "us-east-2"
31+
error_message = "The region should be us-east-2"
32+
}
33+
}
34+
35+
# Simulate the creation of resources in us-east-1 and us-east-2 to make sure resources name do not conflict (IAM roles, etc.)
36+
run "multi_region_us_east_1_existing_resources" {
37+
command = apply
38+
}
39+
40+
run "multi_region_us_east_2_existing_resources" {
41+
command = plan
42+
43+
variables {
44+
region = "us-east-2"
45+
}
46+
}

variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,9 @@ variable "tags" {
380380
default = {}
381381
description = "A map of tags to assign to all AWS resources created by this module that support tagging."
382382
}
383+
384+
variable "region" {
385+
type = string
386+
description = "AWS region to deploy the Datadog Forwarder to. If empty, the forwarder will be deployed to the region set by the provider."
387+
default = null
388+
}

0 commit comments

Comments
 (0)