Skip to content

Commit 4308a9e

Browse files
committed
Initial commit
1 parent 3c26557 commit 4308a9e

14 files changed

+2569
-57
lines changed

.github/settings.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
# Upstream changes from _extends are only recognized when modifications are made to this file in the default branch.
22
_extends: .github
33
repository:
4-
name: template
5-
description: Template for Terraform Components
4+
name: aws-ecs-service
5+
description: This component is responsible for creating an ECS service
66
homepage: https://cloudposse.com/accelerate
77
topics: terraform, terraform-component
8-
9-
10-
11-

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## PR [#1008](https://github.com/cloudposse/terraform-aws-components/pull/1008)
2+
3+
### Possible Breaking Change
4+
5+
- Refactored how S3 Task Definitions and the Terraform Task definition are merged.
6+
- Introduced local `local.containers_priority_terraform` to be referenced whenever terraform Should take priority
7+
- Introduced local `local.containers_priority_s3` to be referenced whenever S3 Should take priority
8+
- `map_secrets` pulled out from container definition to local where it can be better maintained. Used Terraform as
9+
priority as it is a calculated as a map of arns.
10+
- `s3_mirror_name` now automatically uploads a task-template.json to s3 mirror where it can be pulled from GitHub
11+
Actions.

README.yaml

Lines changed: 479 additions & 47 deletions
Large diffs are not rendered by default.

src/cloud-map.tf

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Service Connect
2+
3+
module "cloudmap_namespace" {
4+
for_each = { for service_connect in var.service_connect_configurations : service_connect.namespace => service_connect }
5+
6+
source = "cloudposse/stack-config/yaml//modules/remote-state"
7+
version = "1.5.0"
8+
9+
component = each.key
10+
11+
# we ignore errors because the namespace may be a name or an arn of a namespace for the service.
12+
ignore_errors = true
13+
context = module.this.context
14+
}
15+
16+
locals {
17+
valid_cloudmap_namespaces = { for k, v in module.cloudmap_namespace : k => v if v.outputs != null }
18+
service_connect_configurations = [for service_connect in var.service_connect_configurations : merge(service_connect, { namespace = try(local.valid_cloudmap_namespaces[service_connect.namespace].outputs.name, service_connect.namespace) })]
19+
}
20+
// ------------------------------
21+
22+
// Service Discovery
23+
24+
module "cloudmap_namespace_service_discovery" {
25+
for_each = { for service_connect in var.service_registries : service_connect.namespace => service_connect }
26+
27+
source = "cloudposse/stack-config/yaml//modules/remote-state"
28+
version = "1.5.0"
29+
30+
component = each.key
31+
32+
# we ignore errors because the namespace may be a name or an arn of a namespace for the service.
33+
ignore_errors = true
34+
context = module.this.context
35+
}
36+
37+
locals {
38+
valid_cloudmap_service_discovery_namespaces = { for k, v in module.cloudmap_namespace_service_discovery : k => v if v.outputs != null }
39+
service_discovery_configurations = [for service_registry in var.service_registries : merge(service_registry, { namespace = try(local.valid_cloudmap_service_discovery_namespaces[service_registry.namespace].outputs.name, service_registry.namespace) })]
40+
service_config_with_id = { for service_registry in var.service_registries : service_registry.namespace => merge(service_registry, { id = try(local.valid_cloudmap_service_discovery_namespaces[service_registry.namespace].outputs.id, null) }) }
41+
service_discovery = [for value in var.service_registries : merge(value, {
42+
registry_arn = aws_service_discovery_service.default[value.namespace].arn
43+
})]
44+
}
45+
46+
resource "aws_service_discovery_service" "default" {
47+
for_each = local.service_config_with_id
48+
name = module.this.name
49+
50+
dns_config {
51+
namespace_id = each.value.id
52+
53+
dns_records {
54+
ttl = 10
55+
type = "A"
56+
}
57+
58+
routing_policy = "MULTIVALUE"
59+
}
60+
61+
health_check_custom_config {
62+
failure_threshold = 1
63+
}
64+
}
65+
66+
// ------------------------------

src/datadog-agent.tf

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
variable "datadog_agent_sidecar_enabled" {
2+
type = bool
3+
default = false
4+
description = "Enable the Datadog Agent Sidecar"
5+
}
6+
7+
variable "datadog_log_method_is_firelens" {
8+
type = bool
9+
default = false
10+
description = "Datadog logs can be sent via cloudwatch logs (and lambda) or firelens, set this to true to enable firelens via a sidecar container for fluentbit"
11+
}
12+
13+
variable "datadog_sidecar_containers_logs_enabled" {
14+
type = bool
15+
default = true
16+
description = "Enable the Datadog Agent Sidecar to send logs to aws cloudwatch group, requires `datadog_agent_sidecar_enabled` to be true"
17+
}
18+
19+
variable "datadog_logging_tags" {
20+
type = map(string)
21+
default = null
22+
description = "Tags to add to all logs sent to Datadog"
23+
}
24+
25+
variable "datadog_logging_default_tags_enabled" {
26+
type = bool
27+
default = true
28+
description = "Add Default tags to all logs sent to Datadog"
29+
}
30+
31+
locals {
32+
default_datadog_tags = var.datadog_logging_default_tags_enabled ? {
33+
env = module.this.stage
34+
account = format("%s-%s-%s", module.this.tenant, module.this.environment, module.this.stage)
35+
} : null
36+
37+
all_dd_tags = join(",", [for k, v in merge(local.default_datadog_tags, var.datadog_logging_tags) : format("%s:%s", k, v)])
38+
39+
datadog_logconfiguration_firelens = {
40+
logDriver = "awsfirelens"
41+
options = var.datadog_agent_sidecar_enabled ? {
42+
Name = "datadog",
43+
apikey = module.datadog_configuration.datadog_api_key,
44+
Host = format("http-intake.logs.%s", module.datadog_configuration.datadog_site)
45+
dd_service = module.this.name,
46+
dd_tags = local.all_dd_tags,
47+
dd_source = "ecs",
48+
dd_message_key = "log",
49+
TLS = "on",
50+
provider = "ecs"
51+
} : {}
52+
}
53+
}
54+
55+
module "datadog_sidecar_logs" {
56+
source = "cloudposse/cloudwatch-logs/aws"
57+
version = "0.6.6"
58+
59+
# if we are using datadog firelens we don't need to create a log group
60+
count = local.enabled && var.datadog_agent_sidecar_enabled && var.datadog_sidecar_containers_logs_enabled ? 1 : 0
61+
62+
stream_names = lookup(var.logs, "stream_names", [])
63+
retention_in_days = lookup(var.logs, "retention_in_days", 90)
64+
65+
principals = merge({
66+
Service = ["ecs.amazonaws.com", "ecs-tasks.amazonaws.com"]
67+
}, lookup(var.logs, "principals", {}))
68+
69+
additional_permissions = concat([
70+
"logs:CreateLogStream",
71+
"logs:DeleteLogStream",
72+
], lookup(var.logs, "additional_permissions", []))
73+
74+
context = module.this.context
75+
}
76+
77+
module "datadog_container_definition" {
78+
source = "cloudposse/ecs-container-definition/aws"
79+
version = "0.58.1"
80+
81+
count = local.enabled && var.datadog_agent_sidecar_enabled ? 1 : 0
82+
83+
container_cpu = 256
84+
container_memory = 512
85+
container_name = "datadog-agent"
86+
container_image = "public.ecr.aws/datadog/agent:latest"
87+
essential = true
88+
map_environment = {
89+
"ECS_FARGATE" = var.task.launch_type == "FARGATE" ? true : false
90+
"DD_API_KEY" = module.datadog_configuration.datadog_api_key
91+
"DD_SITE" = module.datadog_configuration.datadog_site
92+
"DD_ENV" = module.this.stage
93+
"DD_LOGS_ENABLED" = true
94+
"DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL" = true
95+
"SD_BACKEND" = "docker"
96+
"DD_PROCESS_AGENT_ENABLED" = true
97+
"DD_DOGSTATSD_NON_LOCAL_TRAFFIC" = true
98+
"DD_APM_ENABLED" = true
99+
"DD_CONTAINER_LABELS_AS_TAGS" = jsonencode({
100+
"org.opencontainers.image.revision" = "version"
101+
})
102+
}
103+
104+
// Datadog DogStatsD/tracing ports
105+
port_mappings = [{
106+
containerPort = 8125
107+
hostPort = 8125
108+
protocol = "udp"
109+
}, {
110+
containerPort = 8126
111+
hostPort = 8126
112+
protocol = "tcp"
113+
}]
114+
115+
log_configuration = var.datadog_sidecar_containers_logs_enabled ? {
116+
logDriver = "awslogs"
117+
options = {
118+
"awslogs-group" = one(module.datadog_sidecar_logs[*].log_group_name)
119+
"awslogs-region" = var.region
120+
"awslogs-stream-prefix" = "datadog-agent"
121+
}
122+
} : null
123+
}
124+
125+
module "datadog_fluent_bit_container_definition" {
126+
source = "cloudposse/ecs-container-definition/aws"
127+
version = "0.58.1"
128+
129+
count = local.enabled && var.datadog_agent_sidecar_enabled ? 1 : 0
130+
131+
container_cpu = 256
132+
container_memory = 512
133+
container_name = "datadog-log-router"
134+
# From Datadog Support:
135+
# In this case, the newest container image with the latest tag (corresponding to version 2.29.0) looks like it is crashing for certain customers, which is causing the Task to deprovision.
136+
# Note: We recommend customers to use the stable tag for this type of reason
137+
container_image = "amazon/aws-for-fluent-bit:stable"
138+
essential = true
139+
firelens_configuration = {
140+
type = "fluentbit"
141+
options = {
142+
config-file-type = "file",
143+
config-file-value = "/fluent-bit/configs/parse-json.conf",
144+
enable-ecs-log-metadata = "true"
145+
}
146+
}
147+
148+
log_configuration = var.datadog_sidecar_containers_logs_enabled ? {
149+
logDriver = "awslogs"
150+
options = {
151+
"awslogs-group" = one(module.datadog_sidecar_logs[*].log_group_name)
152+
"awslogs-region" = var.region
153+
"awslogs-stream-prefix" = "datadog-log-router"
154+
}
155+
} : null
156+
}

0 commit comments

Comments
 (0)