From 850e210ed8594eae0beaca1f5a4ea8c55edbd4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Fr=C3=B6mbgen?= <23717573+mfroembgen@users.noreply.github.com> Date: Wed, 26 Jul 2023 16:59:53 +0200 Subject: [PATCH] feat!: add_common_capabilities (#21) --- README.md | 102 +++++++------ alb.tf | 22 +++ autoscaling.tf | 22 +-- data.tf | 39 ++++- ecr.tf | 50 +++++++ examples/basic/main.tf | 28 ---- examples/basic/outputs.tf | 0 examples/basic/providers.tf | 3 - examples/basic/variables.tf | 0 examples/basic/versions.tf | 9 -- main.tf | 94 +++++++++--- monitoring.tf | 29 ++++ outputs.tf | 97 ------------ provider.tf | 20 +++ sentry.tf | 10 ++ variables.tf | 291 ++++++++++++++++++++++++++++-------- versions.tf | 23 ++- 17 files changed, 564 insertions(+), 275 deletions(-) create mode 100644 alb.tf create mode 100644 ecr.tf delete mode 100644 examples/basic/main.tf delete mode 100644 examples/basic/outputs.tf delete mode 100644 examples/basic/providers.tf delete mode 100644 examples/basic/variables.tf delete mode 100644 examples/basic/versions.tf create mode 100644 monitoring.tf create mode 100644 provider.tf create mode 100644 sentry.tf diff --git a/README.md b/README.md index c3a92f2..9efab63 100644 --- a/README.md +++ b/README.md @@ -7,44 +7,72 @@ Terraform module which creates a ecs app | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.3.0 | -| [aws](#requirement\_aws) | >= 4.30.0 | +| [aws](#requirement\_aws) | >= 4.67 | +| [elasticsearch](#requirement\_elasticsearch) | 2.0.7 | +| [elasticstack](#requirement\_elasticstack) | 0.5.0 | +| [gosoline](#requirement\_gosoline) | 1.0.0 | +| [grafana](#requirement\_grafana) | 1.40.1 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.30.0 | +| [aws](#provider\_aws) | >= 4.67 | ## Modules | Name | Source | Version | |------|--------|---------| -| [cloudwatch\_label](#module\_cloudwatch\_label) | cloudposse/label/null | 0.25.0 | -| [container\_definition](#module\_container\_definition) | cloudposse/ecs-container-definition/aws | 0.58.1 | -| [container\_definition\_fluentbit](#module\_container\_definition\_fluentbit) | cloudposse/ecs-container-definition/aws | 0.58.1 | -| [ecs\_label](#module\_ecs\_label) | cloudposse/label/null | 0.25.0 | -| [ecs\_service\_task\_customized\_autoscaling](#module\_ecs\_service\_task\_customized\_autoscaling) | justtrackio/ecs-autoscaling/aws | 1.0.0 | -| [ecs\_service\_task\_predefined\_autoscaling](#module\_ecs\_service\_task\_predefined\_autoscaling) | justtrackio/ecs-autoscaling/aws | 1.0.0 | -| [ecs\_service\_task\_schedule](#module\_ecs\_service\_task\_schedule) | justtrackio/ecs-autoscaling/aws | 1.0.0 | -| [service\_task](#module\_service\_task) | justtrackio/ecs-alb-service-task/aws | 1.0.0 | -| [ssm\_label](#module\_ssm\_label) | cloudposse/label/null | 0.25.0 | -| [this](#module\_this) | cloudposse/label/null | 0.25.0 | +| [alb\_ingress](#module\_alb\_ingress) | cloudposse/alb-ingress/aws | 0.25.1 | +| [cloudwatch\_label](#module\_cloudwatch\_label) | justtrackio/label/null | 0.26.0 | +| [container\_definition](#module\_container\_definition) | cloudposse/ecs-container-definition/aws | 0.58.3 | +| [container\_definition\_fluentbit](#module\_container\_definition\_fluentbit) | cloudposse/ecs-container-definition/aws | 0.58.3 | +| [ecr](#module\_ecr) | terraform-aws-modules/ecr/aws | 1.6.0 | +| [ecr\_label](#module\_ecr\_label) | justtrackio/label/null | 0.26.0 | +| [ecs\_label](#module\_ecs\_label) | justtrackio/label/null | 0.26.0 | +| [ecs\_service\_task\_customized\_autoscaling](#module\_ecs\_service\_task\_customized\_autoscaling) | justtrackio/ecs-autoscaling/aws | 1.1.0 | +| [ecs\_service\_task\_predefined\_autoscaling](#module\_ecs\_service\_task\_predefined\_autoscaling) | justtrackio/ecs-autoscaling/aws | 1.1.0 | +| [ecs\_service\_task\_schedule](#module\_ecs\_service\_task\_schedule) | justtrackio/ecs-autoscaling/aws | 1.1.0 | +| [monitoring](#module\_monitoring) | justtrackio/ecs-gosoline-monitoring/aws | 2.1.0 | +| [sentry](#module\_sentry) | justtrackio/project/sentry | 1.1.1 | +| [service\_task](#module\_service\_task) | justtrackio/ecs-alb-service-task/aws | 1.2.0 | +| [ssm\_label](#module\_ssm\_label) | justtrackio/label/null | 0.26.0 | +| [this](#module\_this) | justtrackio/label/null | 0.26.0 | ## Resources | Name | Type | |------|------| | [aws_cloudwatch_log_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_ecs_cluster.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecs_cluster) | data source | +| [aws_lb.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/lb) | data source | +| [aws_lb_listener.http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/lb_listener) | data source | +| [aws_lb_listener.https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/lb_listener) | data source | | [aws_ssm_parameter.container_cpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | | [aws_ssm_parameter.container_memory_reservation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | | [aws_ssm_parameter.container_tag](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_ssm_parameter.grafana_token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_ssm_parameter.sentry_token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_vpc.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | -| [app\_image\_repository](#input\_app\_image\_repository) | Container registry repository url | `string` | `""` | no | +| [alarm\_consumer](#input\_alarm\_consumer) | This can be used to override alarms for consumers. Keys are names of the consumers. |
object({
alarm_description = optional(string)
datapoints_to_alarm = optional(number, 1)
evaluation_periods = optional(number, 1)
period = optional(number, 60)
success_rate_threshold = optional(number, 99)
})
| `{}` | no | +| [alarm\_enabled](#input\_alarm\_enabled) | Defines if alarms should be created | `bool` | `false` | no | +| [alarm\_gateway](#input\_alarm\_gateway) | This can be used to override alarms for gateway routes. Keys are names of the gateway route. |
object({
alarm_description = optional(string)
datapoints_to_alarm = optional(number, 3)
evaluation_periods = optional(number, 3)
period = optional(number, 60)
success_rate_threshold = optional(number, 99)
})
| `{}` | no | +| [alarm\_kinsumer](#input\_alarm\_kinsumer) | This can be used to override alarms for kinsumers. Keys are names of the kinsumers. |
object({
alarm_description = optional(string)
datapoints_to_alarm = optional(number, 1)
evaluation_periods = optional(number, 1)
period = optional(number, 60)
threshold_seconds_behind = optional(number, 60)
})
| `{}` | no | +| [alarm\_scheduled](#input\_alarm\_scheduled) | This can be used to override scheduled alarm |
object({
alarm_description = optional(string)
datapoints_to_alarm = optional(number, 1)
evaluation_periods = optional(number, 1)
period = optional(number, 60)
threshold = optional(number, 0)
})
| `{}` | no | +| [alb\_health\_check\_interval](#input\_alb\_health\_check\_interval) | The duration in seconds in between health checks | `number` | `30` | no | +| [alb\_health\_check\_matcher](#input\_alb\_health\_check\_matcher) | The HTTP response codes to indicate a healthy check | `string` | `"200"` | no | +| [alb\_health\_check\_path](#input\_alb\_health\_check\_path) | The destination for the health check request | `string` | `"/health"` | no | +| [alb\_name](#input\_alb\_name) | Name of the alb used to attach the target group | `string` | `""` | no | +| [alb\_stickiness\_enabled](#input\_alb\_stickiness\_enabled) | Boolean to enable / disable `stickiness`. Default is `true` | `bool` | `false` | no | +| [alb\_unauthenticated\_hosts](#input\_alb\_unauthenticated\_hosts) | Unauthenticated hosts to match in Hosts header | `list(string)` | `[]` | no | +| [alb\_unauthenticated\_paths](#input\_alb\_unauthenticated\_paths) | Unauthenticated path pattern to match (a maximum of 1 can be defined) | `list(string)` |
[
"*"
]
| no | +| [alb\_unauthenticated\_priority](#input\_alb\_unauthenticated\_priority) | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `authenticated_priority` since a listener can't have multiple rules with the same priority | `number` | `100` | no | | [app\_image\_tag](#input\_app\_image\_tag) | The default container image to use in container definition | `string` | `null` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [autoscaling\_customized\_metric\_name](#input\_autoscaling\_customized\_metric\_name) | The name of the metric | `string` | `""` | no | @@ -59,8 +87,8 @@ Terraform module which creates a ecs app | [autoscaling\_scale\_out\_cooldown](#input\_autoscaling\_scale\_out\_cooldown) | The amount of time, in seconds, after a scale out activity completes before another scale out activity can start | `number` | `60` | no | | [autoscaling\_schedule](#input\_autoscaling\_schedule) | Provides an Application AutoScaling ScheduledAction resource |
list(object({
schedule = string
min_capacity = number
max_capacity = number
}))
| `[]` | no | | [autoscaling\_target\_value](#input\_autoscaling\_target\_value) | The target value for the metric | `number` | `null` | no | -| [aws\_account\_id](#input\_aws\_account\_id) | AWS Account ID | `string` | n/a | yes | -| [aws\_region](#input\_aws\_region) | The AWS region | `string` | `null` | no | +| [aws\_account\_id](#input\_aws\_account\_id) | AWS account id | `string` | `null` | no | +| [aws\_region](#input\_aws\_region) | AWS region | `string` | `null` | no | | [circuit\_breaker\_deployment\_enabled](#input\_circuit\_breaker\_deployment\_enabled) | If `true`, enable the deployment circuit breaker logic for the service | `bool` | `false` | no | | [circuit\_breaker\_rollback\_enabled](#input\_circuit\_breaker\_rollback\_enabled) | If `true`, Amazon ECS will roll back the service if a service deployment fails | `bool` | `false` | no | | [cloudwatch\_log\_group\_enabled](#input\_cloudwatch\_log\_group\_enabled) | A boolean to disable cloudwatch log group creation | `bool` | `true` | no | @@ -78,18 +106,23 @@ Terraform module which creates a ecs app | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [desired\_count](#input\_desired\_count) | The desired number of tasks to start with. Set this to 0 if using DAEMON Service type. (FARGATE does not suppoert DAEMON Service type) | `number` | `1` | no | | [docker\_labels](#input\_docker\_labels) | The configuration options to send to the `docker_labels` | `map(string)` | `null` | no | -| [ecs\_cluster\_arn](#input\_ecs\_cluster\_arn) | The ECS Cluster ARN where ECS Service will be provisioned | `string` | n/a | yes | -| [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | The ECS Cluster Name used by scaling resources | `string` | n/a | yes | +| [domain](#input\_domain) | The default domain | `string` | n/a | yes | +| [elasticsearch\_host](#input\_elasticsearch\_host) | Defines the elasticsearch host to query for logs | `string` | `null` | no | +| [elasticsearch\_index\_template](#input\_elasticsearch\_index\_template) | This defines the properties used within the index template (Only used if create\_elasticsearch\_data\_stream is true) |
object({
additional_fields = map(any)
name = string
priority = number
node_name = string
number_of_shards = number
number_of_replicas = number
})
|
{
"additional_fields": {},
"name": "",
"node_name": "*",
"number_of_replicas": 1,
"number_of_shards": 1,
"priority": 250
}
| no | +| [elasticsearch\_lifecycle\_policy](#input\_elasticsearch\_lifecycle\_policy) | This defines the properties used within the index lifecycle management policy (Only used if create\_elasticsearch\_data\_stream is true) |
object({
delete_phase_min_age = string
hot_phase_max_primary_shard_size = string
hot_phase_max_age = optional(string)
warm_phase_min_age = string
warm_phase_number_of_replicas = number
})
|
{
"delete_phase_min_age": "28d",
"hot_phase_max_primary_shard_size": "10gb",
"warm_phase_min_age": "1d",
"warm_phase_number_of_replicas": 0
}
| no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | | [exec\_enabled](#input\_exec\_enabled) | Specifies whether to enable Amazon ECS Exec for the tasks within the service | `bool` | `true` | no | +| [gosoline\_metadata](#input\_gosoline\_metadata) | Define custom metadata for the gosoline provider |
object({
domain = optional(string),
use_https = optional(string),
port = optional(string)
})
| `null` | no | +| [gosoline\_name\_patterns](#input\_gosoline\_name\_patterns) | Define custom name patters for the gosoline provider |
object({
hostname = optional(string),
cloudwatch_namespace = optional(string),
ecs_cluster = optional(string),
ecs_service = optional(string),
grafana_cloudwatch_datasource = optional(string),
grafana_elasticsearch_datasource = optional(string)
})
|
{
"cloudwatch_namespace": "{env}/{group}/{app}",
"ecs_cluster": "{env}",
"ecs_service": "{group}-{app}",
"grafana_cloudwatch_datasource": "cloudwatch-{family}",
"grafana_elasticsearch_datasource": "elasticsearch-{env}-logs-{group}-{app}",
"hostname": "{scheme}://{app}.{group}.{env}.{metadata_domain}:{port}"
}
| no | +| [grafana\_dashboard\_url](#input\_grafana\_dashboard\_url) | Url of the grafana dashboard | `string` | `null` | no | | [healthcheck](#input\_healthcheck) | A map containing command (string), timeout, interval (duration in seconds), retries (1-10, number of times to retry before marking container unhealthy), and startPeriod (0-300, optional grace period to wait, in seconds, before failed healthchecks count toward retries) |
object({
command = list(string)
retries = number
timeout = number
interval = number
startPeriod = number
})
| `null` | no | | [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | | [ignore\_changes\_desired\_count](#input\_ignore\_changes\_desired\_count) | Whether to ignore changes for desired count in the ECS service | `bool` | `true` | no | | [ignore\_changes\_task\_definition](#input\_ignore\_changes\_task\_definition) | Ignore changes (like environment variables) to the ECS task definition | `bool` | `false` | no | | [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | -| [label\_orders](#input\_label\_orders) | Overrides the `labels_order` for the different labels to modify ID elements appear in the `id` |
object({
cloudwatch = optional(list(string)),
ecs = optional(list(string)),
iam = optional(list(string)),
ssm = optional(list(string)),
vpc = optional(list(string))
})
| `{}` | no | +| [label\_orders](#input\_label\_orders) | Overrides the `labels_order` for the different labels to modify ID elements appear in the `id` |
object({
cloudwatch = optional(list(string), ["environment", "stage", "name"]),
ecr = optional(list(string)),
ecs = optional(list(string), ["stage", "name"]),
ec2 = optional(list(string), ["environment", "stage", "name"]),
iam = optional(list(string)),
sentry = optional(list(string), ["stage", "name"]),
ssm = optional(list(string)),
vpc = optional(list(string)),
elasticsearch = optional(list(string), ["environment", "stage", "name"])
})
| `{}` | no | | [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | | [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | | [launch\_type](#input\_launch\_type) | The ECS launch type (valid options: FARGATE or EC2) | `string` | `"EC2"` | no | @@ -97,17 +130,20 @@ Terraform module which creates a ecs app | [log\_retention\_in\_days](#input\_log\_retention\_in\_days) | The number of days to retain logs for the log group | `number` | `1` | no | | [log\_router\_container\_cpu](#input\_log\_router\_container\_cpu) | The log router cpu reservation for the ECS task definition | `string` | `30` | no | | [log\_router\_container\_memory\_reservation](#input\_log\_router\_container\_memory\_reservation) | The log router cpu reservation for the ECS task definition | `string` | `64` | no | -| [log\_router\_image\_repository](#input\_log\_router\_image\_repository) | Container registry repository url | `string` | `""` | no | -| [log\_router\_image\_tag](#input\_log\_router\_image\_tag) | The default container image to use in container definition | `string` | `null` | no | -| [log\_router\_map\_environment](#input\_log\_router\_map\_environment) | The environment variables to pass to the container. This is a map of string: {key: value}. `environment` overrides `map_environment` | `map(string)` | `null` | no | +| [log\_router\_image\_repository](#input\_log\_router\_image\_repository) | Container registry repository url | `string` | n/a | yes | +| [log\_router\_image\_tag](#input\_log\_router\_image\_tag) | The default container image to use in container definition | `string` | `"stable"` | no | | [log\_router\_options](#input\_log\_router\_options) | The log router options to use | `map(string)` |
{
"config-file-type": "file",
"config-file-value": "/fluent-bit/etc/extra.conf"
}
| no | | [log\_router\_type](#input\_log\_router\_type) | The log router type to use | `string` | `"fluentbit"` | no | +| [metric\_enabled](#input\_metric\_enabled) | Defines if metrics should be written | `bool` | n/a | yes | +| [monitoring\_enabled](#input\_monitoring\_enabled) | Defines if the monitoring module should be created | `bool` | `true` | no | | [mpr\_enabled](#input\_mpr\_enabled) | Whether to use the StreamMprMessagesPerRunner metric for autoscaling (gosoline feature), see: https://github.com/justtrackio/gosoline | `bool` | `false` | no | | [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | | [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no | | [network\_mode](#input\_network\_mode) | The network mode to use for the task. This is required to be `awsvpc` for `FARGATE` `launch_type` or `null` for `EC2` `launch_type` | `string` | `null` | no | | [ordered\_placement\_strategy](#input\_ordered\_placement\_strategy) | Service level strategy rules that are taken into consideration during task placement.
List from top to bottom in order of precedence. The maximum number of ordered\_placement\_strategy blocks is 5.
See [`ordered_placement_strategy`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#ordered_placement_strategy) |
list(object({
type = string
field = string
}))
|
[
{
"field": "instanceId",
"type": "spread"
}
]
| no | +| [organizational\_unit](#input\_organizational\_unit) | Usually used to indicate the AWS organizational unit, e.g. 'prod', 'sdlc' | `string` | `null` | no | | [port\_gateway](#input\_port\_gateway) | Define the gateway port | `number` | `8088` | no | +| [port\_grpc](#input\_port\_grpc) | Define the grpc port | `number` | `8081` | no | | [port\_health](#input\_port\_health) | Define the health port | `number` | `8090` | no | | [port\_mappings](#input\_port\_mappings) | The port mappings to configure for the container. This is a list of maps. Each map should contain "containerPort", "hostPort", and "protocol", where "protocol" is one of "tcp" or "udp". If using containers in a task with the awsvpc or host network mode, the hostPort can either be left blank or set to the same value as the containerPort |
list(object({
containerPort = number
hostPort = number
protocol = string
}))
| `[]` | no | | [port\_metadata](#input\_port\_metadata) | Define the metadata port | `number` | `8070` | no | @@ -120,32 +156,12 @@ Terraform module which creates a ecs app | [task\_memory](#input\_task\_memory) | The amount of memory (in MiB) used by the task. If unspecified, it will default to `container_memory`. If using Fargate launch type `task_memory` must match supported cpu value (https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size) | `number` | `null` | no | | [task\_policy\_arns](#input\_task\_policy\_arns) | A list of IAM Policy ARNs to attach to the generated task role. | `list(string)` | `[]` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | +| [tracing\_enabled](#input\_tracing\_enabled) | Defines if tracing should be enabled | `bool` | n/a | yes | | [ulimits](#input\_ulimits) | The ulimits to configure for the container. This is a list of maps. Each map should contain "name", "softLimit" and "hardLimit" |
list(object({
name = string
softLimit = number
hardLimit = number
}))
| `[]` | no | -| [vpc\_id](#input\_vpc\_id) | The VPC ID where resources are created | `string` | `""` | no | | [wait\_for\_steady\_state](#input\_wait\_for\_steady\_state) | If true, it will wait for the service to reach a steady state (like aws ecs wait services-stable) before continuing | `bool` | `true` | no | | [working\_directory](#input\_working\_directory) | The working directory to run commands inside the container | `string` | `"/app"` | no | ## Outputs -| Name | Description | -|------|-------------| -| [cloudwatch\_log\_group](#output\_cloudwatch\_log\_group) | All outputs from `aws_cloudwatch_log_group.default` | -| [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | Cloudwatch log group ARN | -| [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Cloudwatch log group name | -| [container\_definition](#output\_container\_definition) | All outputs from `module.container_definition` | -| [container\_definition\_json](#output\_container\_definition\_json) | JSON encoded list of container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | -| [container\_definition\_json\_map](#output\_container\_definition\_json\_map) | JSON encoded container definitions for use with other terraform resources such as aws\_ecs\_task\_definition | -| [ecs\_exec\_role\_policy\_id](#output\_ecs\_exec\_role\_policy\_id) | The ECS service role policy ID, in the form of `role_name:role_policy_name` | -| [ecs\_exec\_role\_policy\_name](#output\_ecs\_exec\_role\_policy\_name) | ECS service role name | -| [ecs\_service\_name](#output\_ecs\_service\_name) | ECS Service name | -| [ecs\_service\_role\_arn](#output\_ecs\_service\_role\_arn) | ECS Service role ARN | -| [ecs\_service\_security\_group\_id](#output\_ecs\_service\_security\_group\_id) | Security Group ID of the ECS task | -| [ecs\_task\_definition\_family](#output\_ecs\_task\_definition\_family) | ECS task definition family | -| [ecs\_task\_definition\_revision](#output\_ecs\_task\_definition\_revision) | ECS task definition revision | -| [ecs\_task\_exec\_role\_arn](#output\_ecs\_task\_exec\_role\_arn) | ECS Task exec role ARN | -| [ecs\_task\_exec\_role\_name](#output\_ecs\_task\_exec\_role\_name) | ECS Task role name | -| [ecs\_task\_role\_arn](#output\_ecs\_task\_role\_arn) | ECS Task role ARN | -| [ecs\_task\_role\_id](#output\_ecs\_task\_role\_id) | ECS Task role id | -| [ecs\_task\_role\_name](#output\_ecs\_task\_role\_name) | ECS Task role name | -| [service\_task](#output\_service\_task) | All outputs from `module.service_task` | +No outputs. diff --git a/alb.tf b/alb.tf new file mode 100644 index 0000000..5b13b63 --- /dev/null +++ b/alb.tf @@ -0,0 +1,22 @@ +module "alb_ingress" { + count = length(var.alb_name) > 0 ? 1 : 0 + source = "cloudposse/alb-ingress/aws" + version = "0.25.1" + + label_order = var.label_orders.ec2 + + context = module.this.context + vpc_id = data.aws_vpc.default.id + target_type = "instance" + + unauthenticated_priority = var.alb_unauthenticated_priority + unauthenticated_paths = var.alb_unauthenticated_paths + unauthenticated_hosts = var.alb_unauthenticated_hosts + unauthenticated_listener_arns = [data.aws_lb_listener.http[0].arn, data.aws_lb_listener.https[0].arn] + + health_check_path = var.alb_health_check_path + health_check_matcher = var.alb_health_check_matcher + health_check_interval = var.alb_health_check_interval + + stickiness_enabled = var.alb_stickiness_enabled +} diff --git a/autoscaling.tf b/autoscaling.tf index d803620..a7b83b6 100644 --- a/autoscaling.tf +++ b/autoscaling.tf @@ -22,8 +22,8 @@ locals { } module "cloudwatch_label" { - source = "cloudposse/label/null" - version = "0.25.0" + source = "justtrackio/label/null" + version = "0.26.0" delimiter = "/" label_order = var.label_orders.cloudwatch @@ -34,12 +34,12 @@ module "cloudwatch_label" { module "ecs_service_task_predefined_autoscaling" { count = local.predefined_autoscaling_enabled ? 1 : 0 source = "justtrackio/ecs-autoscaling/aws" - version = "1.0.0" + version = "1.1.0" context = module.this.context - aws_account_id = var.aws_account_id - cluster_name = var.ecs_cluster_name + aws_account_id = module.this.aws_account_id + cluster_name = data.aws_ecs_cluster.default.cluster_name service_name = module.this.id enabled = var.autoscaling_enabled min_capacity = var.autoscaling_min_capacity @@ -63,12 +63,12 @@ module "ecs_service_task_predefined_autoscaling" { module "ecs_service_task_customized_autoscaling" { count = local.customized_autoscaling_enabled ? 1 : 0 source = "justtrackio/ecs-autoscaling/aws" - version = "1.0.0" + version = "1.1.0" context = module.this.context - aws_account_id = var.aws_account_id - cluster_name = var.ecs_cluster_name + aws_account_id = module.this.aws_account_id + cluster_name = data.aws_ecs_cluster.default.cluster_name service_name = module.this.id enabled = var.autoscaling_enabled min_capacity = var.autoscaling_min_capacity @@ -94,12 +94,12 @@ module "ecs_service_task_customized_autoscaling" { module "ecs_service_task_schedule" { count = var.autoscaling_enabled && length(var.autoscaling_schedule) > 0 ? 1 : 0 source = "justtrackio/ecs-autoscaling/aws" - version = "1.0.0" + version = "1.1.0" context = module.this.context - aws_account_id = var.aws_account_id - cluster_name = var.ecs_cluster_name + aws_account_id = module.this.aws_account_id + cluster_name = data.aws_ecs_cluster.default.cluster_name service_name = module.this.id enabled = var.autoscaling_enabled schedule = var.autoscaling_schedule diff --git a/data.tf b/data.tf index 7408d6d..08293a2 100644 --- a/data.tf +++ b/data.tf @@ -1,6 +1,6 @@ module "ssm_label" { - source = "cloudposse/label/null" - version = "0.25.0" + source = "justtrackio/label/null" + version = "0.26.0" delimiter = "/" label_order = var.label_orders.ssm @@ -22,3 +22,38 @@ data "aws_ssm_parameter" "container_tag" { count = var.app_image_tag == null ? 1 : 0 name = "/${module.ssm_label.id}/container_tag" } + +data "aws_ecs_cluster" "default" { + cluster_name = module.this.environment +} + +data "aws_ssm_parameter" "sentry_token" { + name = "/sentry/token" +} + +data "aws_vpc" "default" { + tags = { + account_name = "${module.this.organizational_unit}-${module.this.namespace}" + } +} + +data "aws_ssm_parameter" "grafana_token" { + name = "/grafana/token" +} + +data "aws_lb" "default" { + count = length(var.alb_name) > 0 ? 1 : 0 + name = "${module.this.environment}-${var.alb_name}" +} + +data "aws_lb_listener" "http" { + count = length(var.alb_name) > 0 ? 1 : 0 + load_balancer_arn = data.aws_lb.default[0].arn + port = 80 +} + +data "aws_lb_listener" "https" { + count = length(var.alb_name) > 0 ? 1 : 0 + load_balancer_arn = data.aws_lb.default[0].arn + port = 443 +} diff --git a/ecr.tf b/ecr.tf new file mode 100644 index 0000000..4451ef9 --- /dev/null +++ b/ecr.tf @@ -0,0 +1,50 @@ +module "ecr_label" { + source = "justtrackio/label/null" + version = "0.26.0" + + label_order = var.label_orders.ecr + delimiter = "/" + + context = module.this.context +} + +module "ecr" { + source = "terraform-aws-modules/ecr/aws" + version = "1.6.0" + + repository_name = module.ecr_label.id + tags = module.ecr_label.tags + + attach_repository_policy = false + repository_image_scan_on_push = false + repository_image_tag_mutability = "MUTABLE" + repository_force_delete = true + repository_lifecycle_policy = jsonencode({ + rules = [ + { + rulePriority = 1, + description = "Remove untagged images", + selection = { + countNumber = 1 + countType = "imageCountMoreThan" + tagStatus = "untagged" + }, + action = { + type = "expire" + } + }, + { + rulePriority = 2, + description = "Keep last 30 images", + selection = { + tagStatus = "any", + countType = "imageCountMoreThan", + countNumber = 30 + }, + action = { + type = "expire" + } + } + ] + }) +} diff --git a/examples/basic/main.tf b/examples/basic/main.tf deleted file mode 100644 index 820c045..0000000 --- a/examples/basic/main.tf +++ /dev/null @@ -1,28 +0,0 @@ -module "example" { - source = "../.." - - name = "hello-world" - app_image_repository = "nginx" - app_image_tag = "latest" - log_router_image_repository = "public.ecr.aws/aws-observability/aws-for-fluent-bit" - log_router_image_tag = "stable" - ecs_cluster_arn = "arn:aws:ecs:eu-central-1:123456789012:cluster/my-cluster" - aws_region = "eu-central-1" - aws_account_id = "123456789012" - ecs_cluster_name = "my-cluster" - port_gateway = 80 - port_health = 80 - port_metadata = 80 - log_router_options = {} - healthcheck = { - command = [ - "CMD", - "/usr/bin/curl", - "localhost:80" - ], - retries = 3 - timeout = 5 - interval = 10 - startPeriod = 60 - } -} diff --git a/examples/basic/outputs.tf b/examples/basic/outputs.tf deleted file mode 100644 index e69de29..0000000 diff --git a/examples/basic/providers.tf b/examples/basic/providers.tf deleted file mode 100644 index e1bf6a7..0000000 --- a/examples/basic/providers.tf +++ /dev/null @@ -1,3 +0,0 @@ -provider "aws" { - region = "eu-central-1" -} diff --git a/examples/basic/variables.tf b/examples/basic/variables.tf deleted file mode 100644 index e69de29..0000000 diff --git a/examples/basic/versions.tf b/examples/basic/versions.tf deleted file mode 100644 index b834f74..0000000 --- a/examples/basic/versions.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 4.30.0" - } - } - required_version = ">= 1.3.0" -} diff --git a/main.tf b/main.tf index 4894a24..ba33dea 100644 --- a/main.tf +++ b/main.tf @@ -1,12 +1,28 @@ locals { - ecs_load_balancers = local.alb_enabled ? [{ - target_group_arn = var.target_group_arn + ecs_load_balancers = length(var.alb_name) > 0 ? [{ + target_group_arn = module.alb_ingress[0].target_group_arn container_name = module.ecs_label.id elb_name = null container_port = var.port_gateway }] : [] - container_cpu = var.container_cpu != null ? var.container_cpu : data.aws_ssm_parameter.container_cpu[0].value - docker_labels = merge({}, var.docker_labels) + container_cpu = var.container_cpu != null ? var.container_cpu : data.aws_ssm_parameter.container_cpu[0].value + docker_labels = merge({ + Application = "${module.this.name}.${module.this.stage}" + Domain = "${module.this.environment}.${module.this.organizational_unit}.${module.this.namespace}" + "traefik.enable" = true + "traefik.http.routers.metadata-${module.ecs_label.id}.entrypoints" = "metadata" + "traefik.http.routers.metadata-${module.ecs_label.id}.service" = "metadata-${module.ecs_label.id}" + "traefik.http.services.metadata-${module.ecs_label.id}.loadbalancer.server.port" = 8070 + "traefik.http.routers.gateway-${module.ecs_label.id}.entrypoints" = "gateway" + "traefik.http.routers.gateway-${module.ecs_label.id}.service" = "gateway-${module.ecs_label.id}" + "traefik.http.services.gateway-${module.ecs_label.id}.loadbalancer.server.port" = 8088 + "traefik.http.routers.grpc-${module.ecs_label.id}.entrypoints" = "grpc" + "traefik.http.routers.grpc-${module.ecs_label.id}.service" = "grpc-${module.ecs_label.id}" + "traefik.http.services.grpc-${module.ecs_label.id}.loadbalancer.server.port" = 8081 + "traefik.http.routers.health-${module.ecs_label.id}.entrypoints" = "health" + "traefik.http.routers.health-${module.ecs_label.id}.service" = "health-${module.ecs_label.id}" + "traefik.http.services.health-${module.ecs_label.id}.loadbalancer.server.port" = 8090 + }, var.docker_labels) total_cpu = local.container_cpu + var.log_router_container_cpu task_cpu = var.task_cpu != null ? local.total_cpu > var.task_cpu ? local.total_cpu : var.task_cpu : null container_memory = var.container_memory_reservation != null ? var.container_memory_reservation : data.aws_ssm_parameter.container_memory_reservation[0].value @@ -22,6 +38,9 @@ locals { "arn:aws:iam::aws:policy/CloudWatchFullAccess", "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", "arn:aws:iam::aws:policy/AmazonRoute53AutoNamingReadOnlyAccess", + "arn:aws:iam::aws:policy/AWSXrayFullAccess", + "arn:aws:iam::aws:policy/AmazonSQSFullAccess", + "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess", ] default_port_mappings = [ { @@ -34,6 +53,11 @@ locals { hostPort = 0 protocol = "tcp" }, + { + containerPort = var.port_grpc + hostPort = 0 + protocol = "tcp" + }, { containerPort = var.port_metadata hostPort = 0 @@ -45,7 +69,7 @@ locals { "CMD", "/usr/bin/wget", "--spider", - "localhost:${var.port_health}" + "localhost:${var.port_health}/health" ], retries = 3 timeout = 5 @@ -55,8 +79,8 @@ locals { } module "ecs_label" { - source = "cloudposse/label/null" - version = "0.25.0" + source = "justtrackio/label/null" + version = "0.26.0" label_order = var.label_orders.ecs @@ -73,22 +97,46 @@ resource "aws_cloudwatch_log_group" "default" { module "container_definition" { source = "cloudposse/ecs-container-definition/aws" - version = "0.58.1" + version = "0.58.3" container_name = module.ecs_label.id - container_image = "${var.app_image_repository}:${local.image_tag}" + container_image = "${module.ecr.repository_url}:${local.image_tag}" container_memory = var.container_memory container_memory_reservation = var.container_memory_reservation container_cpu = var.container_cpu start_timeout = var.container_start_timeout stop_timeout = var.container_stop_timeout healthcheck = local.healthcheck - map_environment = var.container_map_environment - map_secrets = var.container_map_secrets - port_mappings = local.port_mappings - ulimits = var.ulimits - working_directory = var.working_directory - docker_labels = local.docker_labels + map_environment = merge({ + AWS_SDK_RETRIES = 10 + AWS_DEFAULT_REGION = module.this.aws_region + ENV = module.this.environment + ENVIRONMENT = module.this.environment + SENTRY_DSN = module.sentry.dsn + SENTRY_ENVIRONMENT = module.this.environment + METRIC_ENABLED = var.metric_enabled + METRIC_WRITER = "cw" + REDIS_DEFAULT_ADDRESS = "" + REDIS_DEFAULT_DIALER = "srv" + CLOUD_AWS_DEFAULTS_ENDPOINT = "" + LOG_HANDLERS_MAIN_FORMATTER = "json" + LOG_HANDLERS_MAIN_TIMESTAMP_FORMAT = "2006-01-02T15:04:05.999Z07:00" + STREAM_METRICS_MESSAGES_PER_RUNNER_ECS_SERVICE = "{app_group}-{app_name}" + STREAM_METRICS_MESSAGES_PER_RUNNER_DYNAMODB_NAMING_PATTERN = "!nodecode {env}-{modelId}" + CLOUD_AWS_DYNAMODB_CLIENTS_DEFAULT_NAMING_PATTERN = "!nodecode {env}-{group}-{modelId}" + CLOUD_AWS_SNS_CLIENTS_DEFAULT_NAMING_PATTERN = "!nodecode {env}-{group}-{topicId}" + CLOUD_AWS_SQS_CLIENTS_DEFAULT_NAMING_PATTERN = "!nodecode {env}-{group}-{queueId}" + METRIC_CLOUDWATCH_NAMING_PATTERN = "!nodecode {env}/{group}/{app}" + CLOUD_AWS_KINESIS_CLIENTS_DEFAULT_NAMING_PATTERN = "!nodecode {env}-{group}-{streamName}" + TRACING_ENABLED = var.tracing_enabled + TRACING_ADDR_TYPE = "srv" + FIXTURE_GROUP_NAME = "$FIXTURE_GROUP_NAME" + }, var.container_map_environment) + map_secrets = var.container_map_secrets + port_mappings = local.port_mappings + ulimits = var.ulimits + working_directory = var.working_directory + docker_labels = local.docker_labels log_configuration = { logDriver = var.log_driver @@ -99,7 +147,7 @@ module "container_definition" { module "container_definition_fluentbit" { source = "cloudposse/ecs-container-definition/aws" - version = "0.58.1" + version = "0.58.3" container_name = "log_router" container_image = "${var.log_router_image_repository}:${var.log_router_image_tag}" @@ -114,16 +162,20 @@ module "container_definition_fluentbit" { logDriver = "awslogs" options = { awslogs-group = try(aws_cloudwatch_log_group.default[0].name, ""), - awslogs-region = var.aws_region + awslogs-region = module.this.aws_region } } - map_environment = var.log_router_map_environment + map_environment = { + FLUENTD_HOSTNAME = "fluentd.${module.this.organizational_unit}-monitoring.${var.domain}" + FLUENTD_PORT = 15000 + TAG = "${module.this.environment}-${module.this.namespace}-${module.this.stage}-${module.this.name}" + } } module "service_task" { source = "justtrackio/ecs-alb-service-task/aws" - version = "1.0.0" + version = "1.2.0" circuit_breaker_deployment_enabled = var.circuit_breaker_deployment_enabled circuit_breaker_rollback_enabled = var.circuit_breaker_rollback_enabled @@ -131,7 +183,7 @@ module "service_task" { deployment_maximum_percent = var.deployment_maximum_percent deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent desired_count = var.desired_count - ecs_cluster_arn = var.ecs_cluster_arn + ecs_cluster_arn = data.aws_ecs_cluster.default.arn ecs_load_balancers = local.ecs_load_balancers exec_enabled = var.exec_enabled ignore_changes_desired_count = var.ignore_changes_desired_count @@ -144,7 +196,7 @@ module "service_task" { task_exec_policy_arns = local.task_policies task_memory = local.task_memory task_policy_arns = local.task_policies - vpc_id = var.vpc_id + vpc_id = data.aws_vpc.default.id wait_for_steady_state = var.wait_for_steady_state label_orders = var.label_orders diff --git a/monitoring.tf b/monitoring.tf new file mode 100644 index 0000000..0d4e9e8 --- /dev/null +++ b/monitoring.tf @@ -0,0 +1,29 @@ +locals { + gosoline_metadata = var.gosoline_metadata != null ? var.gosoline_metadata : { + domain = "${module.this.organizational_unit}.${module.this.namespace}" + use_https = false + port = 8070 + } + elasticsearch_host = var.elasticsearch_host != null ? var.elasticsearch_host : "http://elasticsearch.${module.this.organizational_unit}-monitoring.${var.domain}:9200" + grafana_dashboard_url = var.grafana_dashboard_url != null ? var.grafana_dashboard_url : "https://grafana.${module.this.organizational_unit}-monitoring.${var.domain}" +} + +module "monitoring" { + count = var.monitoring_enabled ? 1 : 0 + source = "justtrackio/ecs-gosoline-monitoring/aws" + version = "2.1.0" + + context = module.this.context + + alarm_enabled = var.alarm_enabled + organizational_unit = module.this.organizational_unit + label_orders = var.label_orders + + alarm_consumer = var.alarm_consumer + alarm_gateway = var.alarm_gateway + alarm_kinsumer = var.alarm_kinsumer + alarm_scheduled = var.alarm_scheduled + + elasticsearch_index_template = var.elasticsearch_index_template + elasticsearch_lifecycle_policy = var.elasticsearch_lifecycle_policy +} diff --git a/outputs.tf b/outputs.tf index 4b06cfd..e69de29 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,97 +0,0 @@ -output "container_definition" { - description = "All outputs from `module.container_definition`" - value = module.container_definition - sensitive = true -} - -output "container_definition_json" { - description = "JSON encoded list of container definitions for use with other terraform resources such as aws_ecs_task_definition" - value = module.container_definition.json_map_encoded_list - sensitive = true -} - -output "container_definition_json_map" { - description = "JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition" - value = module.container_definition.json_map_encoded - sensitive = true -} - -output "service_task" { - description = "All outputs from `module.service_task`" - value = module.service_task -} - -output "ecs_exec_role_policy_id" { - description = "The ECS service role policy ID, in the form of `role_name:role_policy_name`" - value = module.service_task.ecs_exec_role_policy_id -} - -output "ecs_exec_role_policy_name" { - description = "ECS service role name" - value = module.service_task.ecs_exec_role_policy_name -} - -output "ecs_service_name" { - description = "ECS Service name" - value = module.service_task.service_name -} - -output "ecs_service_role_arn" { - description = "ECS Service role ARN" - value = module.service_task.service_role_arn -} - -output "ecs_task_exec_role_name" { - description = "ECS Task role name" - value = module.service_task.task_exec_role_name -} - -output "ecs_task_exec_role_arn" { - description = "ECS Task exec role ARN" - value = module.service_task.task_exec_role_arn -} - -output "ecs_task_role_name" { - description = "ECS Task role name" - value = module.service_task.task_role_name -} - -output "ecs_task_role_arn" { - description = "ECS Task role ARN" - value = module.service_task.task_role_arn -} - -output "ecs_task_role_id" { - description = "ECS Task role id" - value = module.service_task.task_role_id -} - -output "ecs_service_security_group_id" { - description = "Security Group ID of the ECS task" - value = module.service_task.service_security_group_id -} - -output "ecs_task_definition_family" { - description = "ECS task definition family" - value = module.service_task.task_definition_family -} - -output "ecs_task_definition_revision" { - description = "ECS task definition revision" - value = module.service_task.task_definition_revision -} - -output "cloudwatch_log_group" { - description = "All outputs from `aws_cloudwatch_log_group.default`" - value = aws_cloudwatch_log_group.default -} - -output "cloudwatch_log_group_arn" { - description = "Cloudwatch log group ARN" - value = try(aws_cloudwatch_log_group.default[0].arn, "") -} - -output "cloudwatch_log_group_name" { - description = "Cloudwatch log group name" - value = try(aws_cloudwatch_log_group.default[0].name, "") -} diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..45f35af --- /dev/null +++ b/provider.tf @@ -0,0 +1,20 @@ +provider "gosoline" { + metadata = local.gosoline_metadata + name_patterns = var.gosoline_name_patterns +} + +provider "grafana" { + url = local.grafana_dashboard_url + auth = data.aws_ssm_parameter.grafana_token.value +} + +provider "elasticsearch" { + url = local.elasticsearch_host +} + +provider "elasticstack" { + elasticsearch { + endpoints = [local.elasticsearch_host] + insecure = true + } +} diff --git a/sentry.tf b/sentry.tf new file mode 100644 index 0000000..4473821 --- /dev/null +++ b/sentry.tf @@ -0,0 +1,10 @@ +module "sentry" { + source = "justtrackio/project/sentry" + version = "1.1.1" + + context = module.this.context + label_order = var.label_orders.sentry + + base_url = "http://sentry.${module.this.organizational_unit}-monitoring.${var.domain}" + token = data.aws_ssm_parameter.sentry_token.value +} diff --git a/variables.tf b/variables.tf index 7100fff..001097a 100644 --- a/variables.tf +++ b/variables.tf @@ -1,9 +1,105 @@ -variable "app_image_repository" { +variable "alarm_consumer" { + type = object({ + alarm_description = optional(string) + datapoints_to_alarm = optional(number, 1) + evaluation_periods = optional(number, 1) + period = optional(number, 60) + success_rate_threshold = optional(number, 99) + }) + default = {} + description = "This can be used to override alarms for consumers. Keys are names of the consumers." +} + +variable "alarm_enabled" { + type = bool + default = false + description = "Defines if alarms should be created" +} + +variable "alarm_gateway" { + type = object({ + alarm_description = optional(string) + datapoints_to_alarm = optional(number, 3) + evaluation_periods = optional(number, 3) + period = optional(number, 60) + success_rate_threshold = optional(number, 99) + }) + default = {} + description = "This can be used to override alarms for gateway routes. Keys are names of the gateway route." +} + +variable "alarm_kinsumer" { + type = object({ + alarm_description = optional(string) + datapoints_to_alarm = optional(number, 1) + evaluation_periods = optional(number, 1) + period = optional(number, 60) + threshold_seconds_behind = optional(number, 60) + }) + default = {} + description = "This can be used to override alarms for kinsumers. Keys are names of the kinsumers." +} + +variable "alarm_scheduled" { + type = object({ + alarm_description = optional(string) + datapoints_to_alarm = optional(number, 1) + evaluation_periods = optional(number, 1) + period = optional(number, 60) + threshold = optional(number, 0) + }) + default = {} + description = "This can be used to override scheduled alarm" +} + +variable "alb_health_check_interval" { + type = number + default = 30 + description = "The duration in seconds in between health checks" +} + +variable "alb_health_check_matcher" { type = string - description = "Container registry repository url" + default = "200" + description = "The HTTP response codes to indicate a healthy check" +} + +variable "alb_health_check_path" { + type = string + default = "/health" + description = "The destination for the health check request" +} + +variable "alb_name" { + type = string + description = "Name of the alb used to attach the target group" default = "" } +variable "alb_stickiness_enabled" { + type = bool + default = false + description = "Boolean to enable / disable `stickiness`. Default is `true`" +} + +variable "alb_unauthenticated_hosts" { + type = list(string) + default = [] + description = "Unauthenticated hosts to match in Hosts header" +} + +variable "alb_unauthenticated_paths" { + type = list(string) + default = ["*"] + description = "Unauthenticated path pattern to match (a maximum of 1 can be defined)" +} + +variable "alb_unauthenticated_priority" { + type = number + default = 100 + description = "The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `authenticated_priority` since a listener can't have multiple rules with the same priority" +} + variable "app_image_tag" { type = string description = "The default container image to use in container definition" @@ -34,18 +130,18 @@ variable "autoscaling_enabled" { description = "Defines if autoscaling should be enabled" } -variable "autoscaling_min_capacity" { - type = number - description = "Minimum number of running instances of a Service" - default = 1 -} - variable "autoscaling_max_capacity" { type = number description = "Maximum number of running instances of a Service" default = 200 } +variable "autoscaling_min_capacity" { + type = number + description = "Minimum number of running instances of a Service" + default = 1 +} + variable "autoscaling_predefined_metric_type" { type = string description = "The metric type" @@ -86,17 +182,6 @@ variable "autoscaling_target_value" { default = null } -variable "aws_account_id" { - type = string - description = "AWS Account ID" -} - -variable "aws_region" { - type = string - description = "The AWS region" - default = null -} - variable "circuit_breaker_deployment_enabled" { type = bool description = "If `true`, enable the deployment circuit breaker logic for the service" @@ -181,14 +266,52 @@ variable "docker_labels" { default = null } -variable "ecs_cluster_arn" { +variable "domain" { type = string - description = "The ECS Cluster ARN where ECS Service will be provisioned" + description = "The default domain" } -variable "ecs_cluster_name" { +variable "elasticsearch_host" { type = string - description = "The ECS Cluster Name used by scaling resources" + default = null + description = "Defines the elasticsearch host to query for logs" +} + +variable "elasticsearch_index_template" { + type = object({ + additional_fields = map(any) + name = string + priority = number + node_name = string + number_of_shards = number + number_of_replicas = number + }) + default = { + additional_fields = {} + name = "" + priority = 250 + node_name = "*" + number_of_shards = 1 + number_of_replicas = 1 + } + description = "This defines the properties used within the index template (Only used if create_elasticsearch_data_stream is true)" +} + +variable "elasticsearch_lifecycle_policy" { + type = object({ + delete_phase_min_age = string + hot_phase_max_primary_shard_size = string + hot_phase_max_age = optional(string) + warm_phase_min_age = string + warm_phase_number_of_replicas = number + }) + default = { + delete_phase_min_age = "28d" + hot_phase_max_primary_shard_size = "10gb" + warm_phase_min_age = "1d" + warm_phase_number_of_replicas = 0 + } + description = "This defines the properties used within the index lifecycle management policy (Only used if create_elasticsearch_data_stream is true)" } variable "exec_enabled" { @@ -197,7 +320,42 @@ variable "exec_enabled" { default = true } -# https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html +variable "gosoline_metadata" { + type = object({ + domain = optional(string), + use_https = optional(string), + port = optional(string) + }) + description = "Define custom metadata for the gosoline provider" + default = null +} + +variable "gosoline_name_patterns" { + type = object({ + hostname = optional(string), + cloudwatch_namespace = optional(string), + ecs_cluster = optional(string), + ecs_service = optional(string), + grafana_cloudwatch_datasource = optional(string), + grafana_elasticsearch_datasource = optional(string) + }) + description = "Define custom name patters for the gosoline provider" + default = { + hostname = "{scheme}://{app}.{group}.{env}.{metadata_domain}:{port}" + cloudwatch_namespace = "{env}/{group}/{app}" + ecs_cluster = "{env}" + ecs_service = "{group}-{app}" + grafana_cloudwatch_datasource = "cloudwatch-{family}" + grafana_elasticsearch_datasource = "elasticsearch-{env}-logs-{group}-{app}" + } +} + +variable "grafana_dashboard_url" { + type = string + description = "Url of the grafana dashboard" + default = null +} + variable "healthcheck" { type = object({ command = list(string) @@ -210,16 +368,32 @@ variable "healthcheck" { default = null } +variable "ignore_changes_desired_count" { + type = bool + description = "Whether to ignore changes for desired count in the ECS service" + default = true +} + variable "ignore_changes_task_definition" { type = bool description = "Ignore changes (like environment variables) to the ECS task definition" default = false } -variable "ignore_changes_desired_count" { - type = bool - description = "Whether to ignore changes for desired count in the ECS service" - default = true +variable "label_orders" { + type = object({ + cloudwatch = optional(list(string), ["environment", "stage", "name"]), + ecr = optional(list(string)), + ecs = optional(list(string), ["stage", "name"]), + ec2 = optional(list(string), ["environment", "stage", "name"]), + iam = optional(list(string)), + sentry = optional(list(string), ["stage", "name"]), + ssm = optional(list(string)), + vpc = optional(list(string)), + elasticsearch = optional(list(string), ["environment", "stage", "name"]) + }) + default = {} + description = "Overrides the `labels_order` for the different labels to modify ID elements appear in the `id`" } variable "launch_type" { @@ -255,19 +429,12 @@ variable "log_router_container_memory_reservation" { variable "log_router_image_repository" { type = string description = "Container registry repository url" - default = "" } variable "log_router_image_tag" { type = string description = "The default container image to use in container definition" - default = null -} - -variable "log_router_map_environment" { - type = map(string) - description = "The environment variables to pass to the container. This is a map of string: {key: value}. `environment` overrides `map_environment`" - default = null + default = "stable" } variable "log_router_options" { @@ -285,6 +452,17 @@ variable "log_router_type" { default = "fluentbit" } +variable "metric_enabled" { + type = bool + description = "Defines if metrics should be written" +} + +variable "monitoring_enabled" { + type = bool + default = true + description = "Defines if the monitoring module should be created" +} + variable "mpr_enabled" { type = bool description = "Whether to use the StreamMprMessagesPerRunner metric for autoscaling (gosoline feature), see: https://github.com/justtrackio/gosoline" @@ -319,6 +497,12 @@ variable "port_gateway" { default = 8088 } +variable "port_grpc" { + type = number + description = "Define the grpc port" + default = 8081 +} + variable "port_health" { type = number description = "Define the health port" @@ -341,12 +525,6 @@ variable "port_metadata" { default = 8070 } -variable "target_group_arn" { - type = string - description = "The ARN of the Target Group to which to route traffic" - default = "" -} - variable "service_placement_constraints" { type = list(object({ type = string @@ -356,6 +534,12 @@ variable "service_placement_constraints" { default = [] } +variable "target_group_arn" { + type = string + description = "The ARN of the Target Group to which to route traffic" + default = "" +} + variable "task_cpu" { type = number description = "The number of CPU units used by the task. If unspecified, it will default to `container_cpu`. If using `FARGATE` launch type `task_cpu` must match supported memory values (https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size)" @@ -374,6 +558,11 @@ variable "task_policy_arns" { default = [] } +variable "tracing_enabled" { + type = bool + description = "Defines if tracing should be enabled" +} + variable "ulimits" { type = list(object({ name = string @@ -395,21 +584,3 @@ variable "working_directory" { description = "The working directory to run commands inside the container" default = "/app" } - -variable "vpc_id" { - type = string - description = "The VPC ID where resources are created" - default = "" -} - -variable "label_orders" { - type = object({ - cloudwatch = optional(list(string)), - ecs = optional(list(string)), - iam = optional(list(string)), - ssm = optional(list(string)), - vpc = optional(list(string)) - }) - default = {} - description = "Overrides the `labels_order` for the different labels to modify ID elements appear in the `id`" -} diff --git a/versions.tf b/versions.tf index b834f74..3741fc3 100644 --- a/versions.tf +++ b/versions.tf @@ -2,8 +2,29 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30.0" + version = ">= 4.67" + } + + elasticsearch = { + source = "phillbaker/elasticsearch" + version = "2.0.7" + } + + gosoline = { + source = "justtrackio/gosoline" + version = "1.0.0" + } + + grafana = { + source = "grafana/grafana" + version = "1.40.1" + } + + elasticstack = { + source = "elastic/elasticstack" + version = "0.5.0" } } + required_version = ">= 1.3.0" }