@@ -45,9 +45,11 @@ locals {
45
45
46
46
vpc_public_subnets_ids = ! var. vpc_create ? var. vpc_external_public_subnets_ids : module. vpc . public_subnets
47
47
48
- services_names = keys (var. services )
49
- services = values (var. services )
48
+ services = [for k , v in var . services : merge ({ " name" : k }, v)]
50
49
services_count = length (var. services )
50
+
51
+ # ⚠️ remove when https://github.com/hashicorp/terraform/issues/22560 gets fixed
52
+ services_with_sd = [for s in local . services : s if lookup (s, " service_discovery_enabled" , false )]
51
53
}
52
54
53
55
data "aws_availability_zones" "this" {}
@@ -83,7 +85,7 @@ module "vpc" {
83
85
resource "aws_ecr_repository" "this" {
84
86
count = local. services_count > 0 ? local. services_count : 0
85
87
86
- name = " ${ local . services_names [count . index ]} -${ terraform . workspace } "
88
+ name = " ${ local . services [count . index ]. name } -${ terraform . workspace } "
87
89
}
88
90
89
91
data "template_file" "ecr-lifecycle" {
@@ -99,9 +101,9 @@ data "template_file" "ecr-lifecycle" {
99
101
resource "aws_ecr_lifecycle_policy" "this" {
100
102
count = local. services_count > 0 ? local. services_count : 0
101
103
102
- repository = element ( aws_ecr_repository. this [* ] . name , count. index )
104
+ repository = aws_ecr_repository. this [count . index ] . name
103
105
104
- policy = element ( data. template_file . ecr-lifecycle [* ] . rendered , count. index )
106
+ policy = data. template_file . ecr-lifecycle [count . index ] . rendered
105
107
}
106
108
107
109
# ECS CLUSTER
@@ -129,7 +131,7 @@ data "template_file" "tasks" {
129
131
template = file (" ${ path . cwd } /${ local . services [count . index ]. task_definition } " )
130
132
131
133
vars = {
132
- container_name = local.services_names [count.index]
134
+ container_name = local.services [count.index].name
133
135
container_port = local.services[count.index].container_port
134
136
repository_url = aws_ecr_repository.this[count.index].repository_url
135
137
log_group = aws_cloudwatch_log_group.this[count.index].name
@@ -140,7 +142,7 @@ data "template_file" "tasks" {
140
142
resource "aws_ecs_task_definition" "this" {
141
143
count = local. services_count > 0 ? local. services_count : 0
142
144
143
- family = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} "
145
+ family = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } "
144
146
container_definitions = data. template_file . tasks [count . index ]. rendered
145
147
requires_compatibilities = [" FARGATE" ]
146
148
network_mode = " awsvpc"
@@ -159,7 +161,7 @@ data "aws_ecs_task_definition" "this" {
159
161
resource "aws_cloudwatch_log_group" "this" {
160
162
count = local. services_count > 0 ? local. services_count : 0
161
163
162
- name = " /ecs/${ var . name } -${ local . services_names [count . index ]} "
164
+ name = " /ecs/${ var . name } -${ local . services [count . index ]. name } "
163
165
164
166
retention_in_days = lookup (local. services [count . index ], " logs_retention_days" , var. cloudwatch_logs_default_retention_days )
165
167
}
@@ -196,7 +198,7 @@ resource "aws_security_group" "services" {
196
198
count = local. services_count > 0 ? local. services_count : 0
197
199
198
200
vpc_id = local. vpc_id
199
- name = " ${ var . name } -${ local . services_names [count . index ]} -${ terraform . workspace } -services-sg"
201
+ name = " ${ var . name } -${ local . services [count . index ]. name } -${ terraform . workspace } -services-sg"
200
202
201
203
ingress {
202
204
from_port = local. services [count . index ]. container_port
@@ -218,7 +220,7 @@ resource "aws_security_group" "services_dynamic" {
218
220
count = local. services_count > 0 ? local. services_count : 0
219
221
220
222
vpc_id = local. vpc_id
221
- name = " ${ var . name } -${ local . services_names [count . index ]} -${ terraform . workspace } -services-sg-dynamic"
223
+ name = " ${ var . name } -${ local . services [count . index ]. name } -${ terraform . workspace } -services-sg-dynamic"
222
224
223
225
egress {
224
226
from_port = 0
@@ -229,7 +231,7 @@ resource "aws_security_group" "services_dynamic" {
229
231
230
232
dynamic "ingress" {
231
233
for_each = [for k , v in var . services : k
232
- if k != local . services_names [count . index ] &&
234
+ if k != local . services [count . index ]. name &&
233
235
contains (lookup (local. services [count . index ], " allow_connections_from" , []), k)]
234
236
235
237
content {
@@ -257,7 +259,7 @@ resource "random_id" "target_group_sufix" {
257
259
resource "aws_lb_target_group" "this" {
258
260
count = local. services_count > 0 ? local. services_count : 0
259
261
260
- name = " ${ var . name } -${ local . services_names [count . index ]} -${ random_id . target_group_sufix [count . index ]. hex } "
262
+ name = " ${ var . name } -${ local . services [count . index ]. name } -${ random_id . target_group_sufix [count . index ]. hex } "
261
263
port = random_id. target_group_sufix [count . index ]. keepers . container_port
262
264
protocol = " HTTP"
263
265
vpc_id = local. vpc_id
@@ -279,7 +281,7 @@ resource "aws_lb_target_group" "this" {
279
281
resource "aws_lb" "this" {
280
282
count = local. services_count > 0 ? local. services_count : 0
281
283
282
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -alb"
284
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -alb"
283
285
subnets = slice (local. vpc_public_subnets_ids , 0 , min (length (data. aws_availability_zones . this . names ), length (local. vpc_public_subnets_ids )))
284
286
security_groups = [aws_security_group . web . id ]
285
287
}
@@ -300,12 +302,46 @@ resource "aws_lb_listener" "this" {
300
302
}
301
303
}
302
304
305
+ # SERVICE DISCOVERY
306
+
307
+ resource "aws_service_discovery_private_dns_namespace" "this" {
308
+ count = length ([for s in local . services : s if lookup (s, " service_discovery_enabled" , false )]) > 0 ? 1 : 0
309
+
310
+ name = " ${ var . name } .${ terraform . workspace } .local"
311
+ description = " ${ var . name } private dns namespace"
312
+ vpc = local. vpc_id
313
+ }
314
+
315
+ resource "aws_service_discovery_service" "this" {
316
+ # ⚠️ replace when https://github.com/hashicorp/terraform/issues/22560 gets fixed
317
+ # for_each = [for s in local.services : s if lookup(s, "service_discovery_enabled", false)]
318
+ count = length (local. services_with_sd ) > 0 ? length (local. services_with_sd ) : 0
319
+
320
+ # name = each.value.name
321
+ name = local. services_with_sd [count . index ]. name
322
+
323
+ dns_config {
324
+ namespace_id = aws_service_discovery_private_dns_namespace. this [0 ]. id
325
+
326
+ dns_records {
327
+ ttl = 10
328
+ type = " A"
329
+ }
330
+
331
+ routing_policy = " MULTIVALUE"
332
+ }
333
+
334
+ health_check_custom_config {
335
+ failure_threshold = 1
336
+ }
337
+ }
338
+
303
339
# ECS SERVICES
304
340
305
341
resource "aws_ecs_service" "this" {
306
342
count = local. services_count > 0 ? local. services_count : 0
307
343
308
- name = local. services_names [count . index ]
344
+ name = local. services [count . index ]. name
309
345
cluster = aws_ecs_cluster. this . name
310
346
task_definition = " ${ aws_ecs_task_definition . this [count . index ]. family } :${ max (" ${ aws_ecs_task_definition . this [count . index ]. revision } " , " ${ data . aws_ecs_task_definition . this [count . index ]. revision } " )} "
311
347
desired_count = local. services [count . index ]. replicas
@@ -326,10 +362,18 @@ resource "aws_ecs_service" "this" {
326
362
327
363
load_balancer {
328
364
target_group_arn = aws_lb_target_group. this [count . index ]. arn
329
- container_name = local. services_names [count . index ]
365
+ container_name = local. services [count . index ]. name
330
366
container_port = local. services [count . index ]. container_port
331
367
}
332
368
369
+ dynamic "service_registries" {
370
+ for_each = [for s in aws_service_discovery_service . this : s if s . name == local . services [count . index ]. name ]
371
+
372
+ content {
373
+ registry_arn = service_registries. value . arn
374
+ }
375
+ }
376
+
333
377
depends_on = [" aws_lb_target_group.this" , " aws_lb_listener.this" ]
334
378
335
379
lifecycle {
@@ -353,7 +397,7 @@ resource "aws_appautoscaling_target" "this" {
353
397
354
398
max_capacity = lookup (local. services [count . index ], " auto_scaling_max_replicas" , local. services [count . index ]. replicas )
355
399
min_capacity = local. services [count . index ]. replicas
356
- resource_id = " service/${ aws_ecs_cluster . this . name } /${ local . services_names [count . index ]} "
400
+ resource_id = " service/${ aws_ecs_cluster . this . name } /${ local . services [count . index ]. name } "
357
401
role_arn = aws_iam_role. autoscaling . arn
358
402
scalable_dimension = " ecs:service:DesiredCount"
359
403
service_namespace = " ecs"
@@ -364,7 +408,7 @@ resource "aws_appautoscaling_target" "this" {
364
408
resource "aws_appautoscaling_policy" "this" {
365
409
count = local. services_count > 0 ? local. services_count : 0
366
410
367
- name = " ${ local . services_names [count . index ]} -autoscaling-policy"
411
+ name = " ${ local . services [count . index ]. name } -autoscaling-policy"
368
412
policy_type = " TargetTrackingScaling"
369
413
resource_id = aws_appautoscaling_target. this [count . index ]. resource_id
370
414
scalable_dimension = aws_appautoscaling_target. this [count . index ]. scalable_dimension
@@ -417,14 +461,14 @@ data "template_file" "buildspec" {
417
461
template = file (" ${ path . module } /build/buildspec.yml" )
418
462
419
463
vars = {
420
- container_name = local.services_names [count.index]
464
+ container_name = local.services [count.index].name
421
465
}
422
466
}
423
467
424
468
resource "aws_codebuild_project" "this" {
425
469
count = local. services_count > 0 ? local. services_count : 0
426
470
427
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -builds"
471
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -builds"
428
472
build_timeout = " 10"
429
473
service_role = aws_iam_role. codebuild . arn
430
474
@@ -451,7 +495,7 @@ resource "aws_codebuild_project" "this" {
451
495
resource "aws_iam_role" "codepipeline" {
452
496
count = local. services_count > 0 ? local. services_count : 0
453
497
454
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -codepipeline-role"
498
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -codepipeline-role"
455
499
456
500
assume_role_policy = file (" ${ path . module } /policies/codepipeline-role.json" )
457
501
}
@@ -470,15 +514,15 @@ data "template_file" "codepipeline" {
470
514
resource "aws_iam_role_policy" "codepipeline" {
471
515
count = local. services_count > 0 ? local. services_count : 0
472
516
473
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -codepipeline-role-policy"
517
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -codepipeline-role-policy"
474
518
role = aws_iam_role. codepipeline [count . index ]. id
475
519
policy = data. template_file . codepipeline [count . index ]. rendered
476
520
}
477
521
478
522
resource "aws_codepipeline" "this" {
479
523
count = local. services_count > 0 ? local. services_count : 0
480
524
481
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -pipeline"
525
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -pipeline"
482
526
role_arn = aws_iam_role. codepipeline [count . index ]. arn
483
527
484
528
artifact_store {
@@ -517,7 +561,7 @@ resource "aws_codepipeline" "this" {
517
561
output_artifacts = [" imagedefinitions" ]
518
562
519
563
configuration = {
520
- ProjectName = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -builds"
564
+ ProjectName = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -builds"
521
565
}
522
566
}
523
567
}
@@ -535,7 +579,7 @@ resource "aws_codepipeline" "this" {
535
579
536
580
configuration = {
537
581
ClusterName = aws_ecs_cluster.this.name
538
- ServiceName = local.services_names [count.index]
582
+ ServiceName = local.services [count.index].name
539
583
FileName = " imagedefinitions.json"
540
584
}
541
585
}
@@ -609,14 +653,14 @@ data "template_file" "metric_dashboard" {
609
653
region = var.region != " " ? var.region : data.aws_region.current.name
610
654
alb_arn_suffix = aws_lb.this[count.index].arn_suffix
611
655
cluster_name = aws_ecs_cluster.this.name
612
- service_name = local.services_names [count.index]
656
+ service_name = local.services [count.index].name
613
657
}
614
658
}
615
659
616
660
resource "aws_cloudwatch_dashboard" "this" {
617
661
count = local. services_count > 0 ? local. services_count : 0
618
662
619
- dashboard_name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -metrics-dashboard"
663
+ dashboard_name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -metrics-dashboard"
620
664
621
665
dashboard_body = data. template_file . metric_dashboard [count . index ]. rendered
622
666
}
@@ -626,7 +670,7 @@ resource "aws_cloudwatch_dashboard" "this" {
626
670
resource "aws_iam_role" "events" {
627
671
count = local. services_count > 0 ? local. services_count : 0
628
672
629
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -events-role"
673
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -events-role"
630
674
631
675
assume_role_policy = file (" ${ path . module } /policies/events-role.json" )
632
676
}
@@ -644,7 +688,7 @@ data "template_file" "events" {
644
688
resource "aws_iam_role_policy" "events" {
645
689
count = local. services_count > 0 ? local. services_count : 0
646
690
647
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -events-role-policy"
691
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -events-role-policy"
648
692
role = aws_iam_role. events [count . index ]. id
649
693
policy = data. template_file . events [count . index ]. rendered
650
694
}
@@ -662,7 +706,7 @@ data "template_file" "ecr_event" {
662
706
resource "aws_cloudwatch_event_rule" "events" {
663
707
count = local. services_count > 0 ? local. services_count : 0
664
708
665
- name = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -ecr-event"
709
+ name = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -ecr-event"
666
710
description = " Amazon CloudWatch Events rule to automatically start your pipeline when a change occurs in the Amazon ECR image tag."
667
711
668
712
event_pattern = data. template_file . ecr_event [count . index ]. rendered
@@ -674,7 +718,7 @@ resource "aws_cloudwatch_event_target" "events" {
674
718
count = local. services_count > 0 ? local. services_count : 0
675
719
676
720
rule = aws_cloudwatch_event_rule. events [count . index ]. name
677
- target_id = " ${ var . name } -${ terraform . workspace } -${ local . services_names [count . index ]} -codepipeline"
721
+ target_id = " ${ var . name } -${ terraform . workspace } -${ local . services [count . index ]. name } -codepipeline"
678
722
arn = aws_codepipeline. this [count . index ]. arn
679
723
role_arn = aws_iam_role. events [count . index ]. arn
680
724
}
0 commit comments