From 2821e223da0c40f1939f0fe625c90fb0b802f862 Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Wed, 19 Oct 2022 15:22:31 -0700 Subject: [PATCH 1/2] Define the type used in extra_container_definitions and utilize in the example --- README.md | 4 +- examples/github-complete/main.tf | 23 ++++ variables.tf | 189 ++++++++++++++++++++++++++++++- versions.tf | 2 +- 4 files changed, 212 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index de73cca4..283d31bb 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ allow_github_webhooks = true | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13.1 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | | [aws](#requirement\_aws) | >= 3.69 | | [random](#requirement\_random) | >= 2.0 | @@ -367,7 +367,7 @@ allow_github_webhooks = true | [ephemeral\_storage\_size](#input\_ephemeral\_storage\_size) | Size of Ephemeral Storage in GiB | `number` | `21` | no | | [essential](#input\_essential) | Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `true` | no | | [external\_task\_definition\_updates](#input\_external\_task\_definition\_updates) | Enable to allow the task definition to be updated outside of this Terraform module. This should be enabled when using a deployment tool such as ecs-deploy which updates the task definition and will then keep the ECS service using the latest version of the task definition. | `bool` | `false` | no | -| [extra\_container\_definitions](#input\_extra\_container\_definitions) | A list of valid container definitions provided as a single valid JSON document. These will be provided as supplimentary to the main Atlantis container definition | `list(any)` | `[]` | no | +| [extra\_container\_definitions](#input\_extra\_container\_definitions) | A list of valid container definitions objects. These will be provided as supplimentary to the main Atlantis container definition |
list(
object({
command = optional(list(string))
cpu = optional(number)
dependsOn = optional(
list(
object({
condition = string
containerName = string
})
)
)
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
entryPoint = optional(list(string))
environment = optional(
list(
object({
name = optional(string)
value = optional(string)
})
)
)
environmentFiles = optional(
list(
object({
type = string
value = string
})
)
)
essential = optional(bool)
extraHosts = optional(
list(
object({
hostname = string
ipAddress = string
})
)
)
firelensConfiguration = optional(
object({
options = map(string)
type = string
})
)
healthCheck = optional(
object({
command = list(string)
interval = optional(number)
retries = optional(number)
startPeriod = optional(number)
timeout = optional(number)
})
)
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(
object({
capabilities = optional(
object(
{
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(
list(
object({
containerPath = optional(string)
hostPath = string
permissions = optional(list(string))
})
)
)
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(
list(
object({
containerPath = string
mountOptions = optional(list(string))
size = number
})
)
)
})
)
logConfiguration = optional(
object({
logDriver = string
options = optional(map(string))
secretOptions = optional(
list(
object({
name = string
valueFrom = string
})
)
)
})
)
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(
list(
object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})
)
)
name = optional(string)
portMappings = optional(
list(
object({
containerPort = optional(number)
hostPort = optional(number)
protocol = optional(string)
})
)
)
privileged = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(
object({
credentialsParameter = string
})
)
resourceRequirements = optional(
list(
object({
type = string
value = string
})
)
)
secrets = optional(
list(
object({
name = string
valueFrom = string
})
)
)
startTimeout = optional(number)
stopTimeout = optional(number)
systemControls = optional(
list(
object({
namespace = optional(string)
valueFrom = optional(string)
})
)
)
ulimits = optional(
list(
object({
hardLimit = number
name = string
softLimit = number
})
)
)
user = optional(string)
volumesFrom = optional(
list(
object({
readOnly = optional(bool)
sourceContainer = optional(string)
})
)
)
workingDirectory = optional(string)
})
)
| `[]` | no | | [extra\_load\_balancers](#input\_extra\_load\_balancers) | A list of maps for additional ECS task load balancers | `list(map(string))` | `[]` | no | | [firelens\_configuration](#input\_firelens\_configuration) | The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html |
object({
type = string
options = map(string)
})
| `null` | no | | [github\_webhooks\_cidr\_blocks](#input\_github\_webhooks\_cidr\_blocks) | List of IPv4 CIDR blocks used by GitHub webhooks | `list(string)` |
[
"140.82.112.0/20",
"185.199.108.0/22",
"192.30.252.0/22",
"143.55.64.0/20"
]
| no | diff --git a/examples/github-complete/main.tf b/examples/github-complete/main.tf index 3fa9f6df..d65aa460 100644 --- a/examples/github-complete/main.tf +++ b/examples/github-complete/main.tf @@ -99,6 +99,29 @@ module "atlantis" { allow_github_webhooks = true allow_repo_config = true + # Extra container definitions + extra_container_definitions = [ + { + name = "log-router" + image = "amazon/aws-for-fluent-bit:latest" + essential = true + + firelens_configuration = { + type = "fluentbit" + + logConfiguration = { + logDriver = "awslogs", + options = { + awslogs-group = "firelens-container", + awslogs-region = local.region, + awslogs-create-group = true, + awslogs-stream-prefix = "firelens" + } + } + } + } + ] + tags = local.tags } diff --git a/variables.tf b/variables.tf index 274b1a3a..c5310154 100644 --- a/variables.tf +++ b/variables.tf @@ -413,10 +413,193 @@ variable "custom_container_definitions" { default = "" } +# Derived from https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html variable "extra_container_definitions" { - description = "A list of valid container definitions provided as a single valid JSON document. These will be provided as supplimentary to the main Atlantis container definition" - type = list(any) - default = [] + description = "A list of valid container definitions objects. These will be provided as supplimentary to the main Atlantis container definition" + type = list( + object({ + command = optional(list(string)) + cpu = optional(number) + dependsOn = optional( + list( + object({ + condition = string + containerName = string + }) + ) + ) + disableNetworking = optional(bool) + dnsSearchDomains = optional(list(string)) + dnsServers = optional(list(string)) + dockerLabels = optional(map(string)) + dockerSecurityOptions = optional(list(string)) + entryPoint = optional(list(string)) + environment = optional( + list( + object({ + name = optional(string) + value = optional(string) + }) + ) + ) + environmentFiles = optional( + list( + object({ + type = string + value = string + }) + ) + ) + essential = optional(bool) + extraHosts = optional( + list( + object({ + hostname = string + ipAddress = string + }) + ) + ) + firelensConfiguration = optional( + object({ + options = map(string) + type = string + }) + ) + healthCheck = optional( + object({ + command = list(string) + interval = optional(number) + retries = optional(number) + startPeriod = optional(number) + timeout = optional(number) + }) + ) + hostname = optional(string) + image = optional(string) + interactive = optional(bool) + links = optional(list(string)) + linuxParameters = optional( + object({ + capabilities = optional( + object( + { + add = optional(list(string)) + drop = optional(list(string)) + })) + devices = optional( + list( + object({ + containerPath = optional(string) + hostPath = string + permissions = optional(list(string)) + }) + ) + ) + initProcessEnabled = optional(bool) + maxSwap = optional(number) + sharedMemorySize = optional(number) + swappiness = optional(number) + tmpfs = optional( + list( + object({ + containerPath = string + mountOptions = optional(list(string)) + size = number + }) + ) + ) + }) + ) + logConfiguration = optional( + object({ + logDriver = string + options = optional(map(string)) + secretOptions = optional( + list( + object({ + name = string + valueFrom = string + }) + ) + ) + }) + ) + memory = optional(number) + memoryReservation = optional(number) + mountPoints = optional( + list( + object({ + containerPath = optional(string) + readOnly = optional(bool) + sourceVolume = optional(string) + }) + ) + ) + name = optional(string) + portMappings = optional( + list( + object({ + containerPort = optional(number) + hostPort = optional(number) + protocol = optional(string) + }) + ) + ) + privileged = optional(bool) + readonlyRootFilesystem = optional(bool) + repositoryCredentials = optional( + object({ + credentialsParameter = string + }) + ) + resourceRequirements = optional( + list( + object({ + type = string + value = string + }) + ) + ) + secrets = optional( + list( + object({ + name = string + valueFrom = string + }) + ) + ) + startTimeout = optional(number) + stopTimeout = optional(number) + systemControls = optional( + list( + object({ + namespace = optional(string) + valueFrom = optional(string) + }) + ) + ) + ulimits = optional( + list( + object({ + hardLimit = number + name = string + softLimit = number + }) + ) + ) + user = optional(string) + volumesFrom = optional( + list( + object({ + readOnly = optional(bool) + sourceContainer = optional(string) + }) + ) + ) + workingDirectory = optional(string) + }) + ) + default = [] } variable "entrypoint" { diff --git a/versions.tf b/versions.tf index c3666f9a..a39e0038 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 0.13.1" + required_version = ">= 1.3.0" required_providers { aws = { From dae2f2d9e9b08fa120e276f375859e6d20a9d1ae Mon Sep 17 00:00:00 2001 From: Michael Kania Date: Fri, 21 Oct 2022 09:17:34 -0700 Subject: [PATCH 2/2] make extra_container_definitions untyped to `any` to get around untyped list comparison issues. --- README.md | 4 +- variables.tf | 189 +-------------------------------------------------- versions.tf | 2 +- 3 files changed, 6 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index 283d31bb..5b0e4c01 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ allow_github_webhooks = true | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [terraform](#requirement\_terraform) | >= 0.13.1 | | [aws](#requirement\_aws) | >= 3.69 | | [random](#requirement\_random) | >= 2.0 | @@ -367,7 +367,7 @@ allow_github_webhooks = true | [ephemeral\_storage\_size](#input\_ephemeral\_storage\_size) | Size of Ephemeral Storage in GiB | `number` | `21` | no | | [essential](#input\_essential) | Determines whether all other containers in a task are stopped, if this container fails or stops for any reason. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `true` | no | | [external\_task\_definition\_updates](#input\_external\_task\_definition\_updates) | Enable to allow the task definition to be updated outside of this Terraform module. This should be enabled when using a deployment tool such as ecs-deploy which updates the task definition and will then keep the ECS service using the latest version of the task definition. | `bool` | `false` | no | -| [extra\_container\_definitions](#input\_extra\_container\_definitions) | A list of valid container definitions objects. These will be provided as supplimentary to the main Atlantis container definition |
list(
object({
command = optional(list(string))
cpu = optional(number)
dependsOn = optional(
list(
object({
condition = string
containerName = string
})
)
)
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
entryPoint = optional(list(string))
environment = optional(
list(
object({
name = optional(string)
value = optional(string)
})
)
)
environmentFiles = optional(
list(
object({
type = string
value = string
})
)
)
essential = optional(bool)
extraHosts = optional(
list(
object({
hostname = string
ipAddress = string
})
)
)
firelensConfiguration = optional(
object({
options = map(string)
type = string
})
)
healthCheck = optional(
object({
command = list(string)
interval = optional(number)
retries = optional(number)
startPeriod = optional(number)
timeout = optional(number)
})
)
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(
object({
capabilities = optional(
object(
{
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(
list(
object({
containerPath = optional(string)
hostPath = string
permissions = optional(list(string))
})
)
)
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(
list(
object({
containerPath = string
mountOptions = optional(list(string))
size = number
})
)
)
})
)
logConfiguration = optional(
object({
logDriver = string
options = optional(map(string))
secretOptions = optional(
list(
object({
name = string
valueFrom = string
})
)
)
})
)
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(
list(
object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})
)
)
name = optional(string)
portMappings = optional(
list(
object({
containerPort = optional(number)
hostPort = optional(number)
protocol = optional(string)
})
)
)
privileged = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(
object({
credentialsParameter = string
})
)
resourceRequirements = optional(
list(
object({
type = string
value = string
})
)
)
secrets = optional(
list(
object({
name = string
valueFrom = string
})
)
)
startTimeout = optional(number)
stopTimeout = optional(number)
systemControls = optional(
list(
object({
namespace = optional(string)
valueFrom = optional(string)
})
)
)
ulimits = optional(
list(
object({
hardLimit = number
name = string
softLimit = number
})
)
)
user = optional(string)
volumesFrom = optional(
list(
object({
readOnly = optional(bool)
sourceContainer = optional(string)
})
)
)
workingDirectory = optional(string)
})
)
| `[]` | no | +| [extra\_container\_definitions](#input\_extra\_container\_definitions) | A list of valid container definitions provided as a single valid JSON document. These will be provided as supplimentary to the main Atlantis container definition | `any` | `[]` | no | | [extra\_load\_balancers](#input\_extra\_load\_balancers) | A list of maps for additional ECS task load balancers | `list(map(string))` | `[]` | no | | [firelens\_configuration](#input\_firelens\_configuration) | The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more details, see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_FirelensConfiguration.html |
object({
type = string
options = map(string)
})
| `null` | no | | [github\_webhooks\_cidr\_blocks](#input\_github\_webhooks\_cidr\_blocks) | List of IPv4 CIDR blocks used by GitHub webhooks | `list(string)` |
[
"140.82.112.0/20",
"185.199.108.0/22",
"192.30.252.0/22",
"143.55.64.0/20"
]
| no | diff --git a/variables.tf b/variables.tf index c5310154..1e5e5017 100644 --- a/variables.tf +++ b/variables.tf @@ -413,193 +413,10 @@ variable "custom_container_definitions" { default = "" } -# Derived from https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html variable "extra_container_definitions" { - description = "A list of valid container definitions objects. These will be provided as supplimentary to the main Atlantis container definition" - type = list( - object({ - command = optional(list(string)) - cpu = optional(number) - dependsOn = optional( - list( - object({ - condition = string - containerName = string - }) - ) - ) - disableNetworking = optional(bool) - dnsSearchDomains = optional(list(string)) - dnsServers = optional(list(string)) - dockerLabels = optional(map(string)) - dockerSecurityOptions = optional(list(string)) - entryPoint = optional(list(string)) - environment = optional( - list( - object({ - name = optional(string) - value = optional(string) - }) - ) - ) - environmentFiles = optional( - list( - object({ - type = string - value = string - }) - ) - ) - essential = optional(bool) - extraHosts = optional( - list( - object({ - hostname = string - ipAddress = string - }) - ) - ) - firelensConfiguration = optional( - object({ - options = map(string) - type = string - }) - ) - healthCheck = optional( - object({ - command = list(string) - interval = optional(number) - retries = optional(number) - startPeriod = optional(number) - timeout = optional(number) - }) - ) - hostname = optional(string) - image = optional(string) - interactive = optional(bool) - links = optional(list(string)) - linuxParameters = optional( - object({ - capabilities = optional( - object( - { - add = optional(list(string)) - drop = optional(list(string)) - })) - devices = optional( - list( - object({ - containerPath = optional(string) - hostPath = string - permissions = optional(list(string)) - }) - ) - ) - initProcessEnabled = optional(bool) - maxSwap = optional(number) - sharedMemorySize = optional(number) - swappiness = optional(number) - tmpfs = optional( - list( - object({ - containerPath = string - mountOptions = optional(list(string)) - size = number - }) - ) - ) - }) - ) - logConfiguration = optional( - object({ - logDriver = string - options = optional(map(string)) - secretOptions = optional( - list( - object({ - name = string - valueFrom = string - }) - ) - ) - }) - ) - memory = optional(number) - memoryReservation = optional(number) - mountPoints = optional( - list( - object({ - containerPath = optional(string) - readOnly = optional(bool) - sourceVolume = optional(string) - }) - ) - ) - name = optional(string) - portMappings = optional( - list( - object({ - containerPort = optional(number) - hostPort = optional(number) - protocol = optional(string) - }) - ) - ) - privileged = optional(bool) - readonlyRootFilesystem = optional(bool) - repositoryCredentials = optional( - object({ - credentialsParameter = string - }) - ) - resourceRequirements = optional( - list( - object({ - type = string - value = string - }) - ) - ) - secrets = optional( - list( - object({ - name = string - valueFrom = string - }) - ) - ) - startTimeout = optional(number) - stopTimeout = optional(number) - systemControls = optional( - list( - object({ - namespace = optional(string) - valueFrom = optional(string) - }) - ) - ) - ulimits = optional( - list( - object({ - hardLimit = number - name = string - softLimit = number - }) - ) - ) - user = optional(string) - volumesFrom = optional( - list( - object({ - readOnly = optional(bool) - sourceContainer = optional(string) - }) - ) - ) - workingDirectory = optional(string) - }) - ) - default = [] + description = "A list of valid container definitions provided as a single valid JSON document. These will be provided as supplimentary to the main Atlantis container definition" + type = any + default = [] } variable "entrypoint" { diff --git a/versions.tf b/versions.tf index a39e0038..c3666f9a 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0" + required_version = ">= 0.13.1" required_providers { aws = {