Skip to content

feat: update container definition including additional parameters to configure #144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
3 changes: 1 addition & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ repos:
hooks:
- id: terraform_fmt
- id: terraform_docs
- id: terraform_validate
- repo: git://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
rev: v3.1.0
hooks:
- id: check-merge-conflict
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ $ cd terraform-aws-atlantis
### Run Atlantis as a Terraform module

This way allows integration with your existing Terraform configurations.

```hcl
module "atlantis" {
source = "terraform-aws-modules/atlantis/aws"
Expand Down Expand Up @@ -157,6 +157,7 @@ allow_github_webhooks = true

## Examples

* [Complete Atlantis with GitHub webhook](https://github.com/terraform-aws-modules/terraform-aws-atlantis/tree/master/examples/github-complete)
* [GitHub repository webhook for Atlantis](https://github.com/terraform-aws-modules/terraform-aws-atlantis/tree/master/examples/github-repository-webhook)
* [GitLab repository webhook for Atlantis](https://github.com/terraform-aws-modules/terraform-aws-atlantis/tree/master/examples/gitlab-repository-webhook)

Expand Down Expand Up @@ -210,33 +211,49 @@ No requirements.
| certificate\_arn | ARN of certificate issued by AWS ACM. If empty, a new ACM certificate will be created and validated using Route53 DNS | `string` | `""` | no |
| cidr | The CIDR block for the VPC which will be created if `vpc_id` is not specified | `string` | `""` | no |
| cloudwatch\_log\_retention\_in\_days | Retention period of Atlantis CloudWatch logs | `number` | `7` | no |
| command | The command that is passed to the container | `list(string)` | `null` | no |
| container\_depends\_on | The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY | <pre>list(object({<br> containerName = string<br> condition = string<br> }))</pre> | `null` | no |
| container\_memory\_reservation | The amount of memory (in MiB) to reserve for the container | `number` | `128` | no |
| create\_route53\_record | Whether to create Route53 record for Atlantis | `bool` | `true` | no |
| custom\_container\_definitions | A list of valid container definitions provided as a single valid JSON document. By default, the standard container definition is used. | `string` | `""` | no |
| custom\_environment\_secrets | List of additional secrets the container will use (list should contain maps with `name` and `valueFrom`) | <pre>list(object(<br> {<br> name = string<br> valueFrom = string<br> }<br> ))</pre> | `[]` | no |
| custom\_environment\_variables | List of additional environment variables the container will use (list should contain maps with `name` and `value`) | <pre>list(object(<br> {<br> name = string<br> value = string<br> }<br> ))</pre> | `[]` | no |
| docker\_labels | The configuration options to send to the `docker_labels` | `map(string)` | `null` | no |
| ecs\_container\_insights | Controls if ECS Cluster has container insights enabled | `bool` | `false` | no |
| ecs\_service\_assign\_public\_ip | Should be true, if ECS service is using public subnets (more info: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_cannot_pull_image.html) | `bool` | `false` | no |
| ecs\_service\_deployment\_maximum\_percent | The upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment | `number` | `200` | no |
| ecs\_service\_deployment\_minimum\_healthy\_percent | The lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment | `number` | `50` | no |
| ecs\_service\_desired\_count | The number of instances of the task definition to place and keep running | `number` | `1` | no |
| ecs\_task\_cpu | The number of cpu units used by the task | `number` | `256` | no |
| ecs\_task\_memory | The amount (in MiB) of memory used by the task | `number` | `512` | no |
| entrypoint | The entry point that is passed to the container | `list(string)` | `null` | no |
| 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 |
| 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 | <pre>object({<br> type = string<br> options = map(string)<br> })</pre> | `null` | no |
| github\_webhooks\_cidr\_blocks | List of CIDR blocks used by GitHub webhooks | `list(string)` | <pre>[<br> "140.82.112.0/20",<br> "185.199.108.0/22",<br> "192.30.252.0/22"<br>]</pre> | no |
| internal | Whether the load balancer is internal or external | `bool` | `false` | no |
| mount\_points | Container mount points. This is a list of maps, where each map should contain a `containerPath` and `sourceVolume`. The `readOnly` key is optional. | `list` | `[]` | no |
| name | Name to use on all resources created (VPC, ALB, etc) | `string` | `"atlantis"` | no |
| policies\_arn | A list of the ARN of the policies you want to apply | `list(string)` | <pre>[<br> "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"<br>]</pre> | no |
| private\_subnet\_ids | A list of IDs of existing private subnets inside the VPC | `list(string)` | `[]` | no |
| private\_subnets | A list of private subnets inside the VPC | `list(string)` | `[]` | no |
| public\_subnet\_ids | A list of IDs of existing public subnets inside the VPC | `list(string)` | `[]` | no |
| public\_subnets | A list of public subnets inside the VPC | `list(string)` | `[]` | no |
| readonly\_root\_filesystem | Determines whether a container is given read-only access to its root filesystem. Due to how Terraform type casts booleans in json it is required to double quote this value | `bool` | `false` | no |
| repository\_credentials | Container repository credentials; required when using a private repo. This map currently supports a single key; "credentialsParameter", which should be the ARN of a Secrets Manager's secret holding the credentials | `map(string)` | `null` | no |
| route53\_record\_name | Name of Route53 record to create ACM certificate in and main A-record. If null is specified, var.name is used instead. Provide empty string to point root domain name to ALB. | `string` | `null` | no |
| route53\_zone\_name | Route53 zone name to create ACM certificate in and main A-record, without trailing dot | `string` | `""` | no |
| security\_group\_ids | List of one or more security groups to be added to the load balancer | `list(string)` | `[]` | no |
| ssm\_kms\_key\_arn | ARN of KMS key to use for encryption and decryption of SSM Parameters. Required only if your key uses a custom KMS key and not the default key | `string` | `""` | no |
| start\_timeout | Time duration (in seconds) to wait before giving up on resolving dependencies for a container | `number` | `30` | no |
| stop\_timeout | Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own | `number` | `30` | no |
| tags | A map of tags to use on all resources | `map(string)` | `{}` | no |
| ulimits | Container ulimit settings. This is a list of maps, where each map should contain "name", "hardLimit" and "softLimit" | <pre>list(object({<br> name = string<br> hardLimit = number<br> softLimit = number<br> }))</pre> | `null` | no |
| user | The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set. | `string` | `null` | no |
| volumes\_from | A list of VolumesFrom maps which contain "sourceContainer" (name of the container that has the volumes to mount) and "readOnly" (whether the container can write to the volume) | <pre>list(object({<br> sourceContainer = string<br> readOnly = bool<br> }))</pre> | `[]` | no |
| vpc\_id | ID of an existing VPC where resources will be created | `string` | `""` | no |
| webhook\_ssm\_parameter\_name | Name of SSM parameter to keep webhook secret | `string` | `"/atlantis/webhook/secret"` | no |
| whitelist\_unauthenticated\_cidr\_blocks | List of allowed CIDR blocks to bypass authentication | `list(string)` | `[]` | no |
| working\_directory | The working directory to run commands inside the container | `string` | `null` | no |

## Outputs

Expand All @@ -249,7 +266,12 @@ No requirements.
| atlantis\_url\_events | Webhook events URL of Atlantis |
| ecs\_security\_group | Security group assigned to ECS Service in network configuration |
| ecs\_task\_definition | Task definition for ECS service (used for external triggers) |
| private\_subnet\_ids | IDs of the VPC private subnets that were created or passed in |
| public\_subnet\_ids | IDs of the VPC public subnets that were created or passed in |
| task\_role\_arn | The Atlantis ECS task role arn |
| task\_role\_id | The Atlantis ECS task role id |
| task\_role\_name | The Atlantis ECS task role name |
| task\_role\_unique\_id | The stable and unique string identifying the Atlantis ECS task role. |
| vpc\_id | ID of the VPC that was created or passed in |
| webhook\_secret | Webhook secret |

Expand Down
60 changes: 60 additions & 0 deletions examples/github-complete/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Complete Atlantis example with GitHub Webhooks

Configuration in this directory creates the necessary infrastructure and resources for running Atlantis on Fargate plus GitHub repository webhooks configured to Atlantis URL.

An existing Route53 hosted zone and domain is required to deploy this example.

GitHub's personal access token can be generated at https://github.com/settings/tokens

## Usage

To run this code you need to copy `terraform.tfvars.sample` into `terraform.tfvars` and update the values locally or specify them using environment variables (`TF_VAR_github_token=xxx`, `TF_VAR_github_organization=xxx`, etc.). Once ready, execute:

```bash
$ terraform init
$ terraform plan
$ terraform apply
```

Note - if you receive the following error when running apply:

`Error: InvalidParameterException: The new ARN and resource ID format must be enabled to add tags to the service. Opt in to the new format and try again. "atlantiscomplete"`

Go to https://eu-west-1.console.aws.amazon.com/ecs/home?region=eu-west-1#/settings (update for your region of use) and change `Container instance`, `Service`, and `Task` to `Enabled`.

⚠️ This example will create resources which cost money. Run `terraform destroy` when you don't need these resources. ⚠️

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

| Name | Version |
|------|---------|
| aws | n/a |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| allowed\_repo\_names | Repositories that Atlantis will listen for events from and a webhook will be installed | `list(string)` | n/a | yes |
| domain | Route53 domain name to use for ACM certificate. Route53 zone for this domain should be created in advance | `string` | n/a | yes |
| github\_organization | Github organization | `string` | n/a | yes |
| github\_token | Github token | `string` | n/a | yes |
| github\_user | Github user for Atlantis to utilize when performing Github activities | `string` | n/a | yes |
| personal\_ip | Your current, personally ip to restrict access to Atlantis UI ending with `/32` for subnet | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| atlantis\_allowed\_repo\_names | Git repositories where webhook should be created |
| atlantis\_url | URL of Atlantis |
| ecs\_task\_definition | Task definition for ECS service (used for external triggers) |
| github\_webhook\_secret | Github webhook secret |
| github\_webhook\_urls | Github webhook URL |
| task\_role\_arn | The Atlantis ECS task role arn |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
211 changes: 211 additions & 0 deletions examples/github-complete/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
provider "aws" {
region = "eu-west-1"
}

locals {
tags = {
Owner = "user"
Environment = "dev"
}
}

##############################################################
# Data sources for existing resources
##############################################################

data "aws_caller_identity" "current" {}

data "aws_region" "current" {}

##############################################################
# Atlantis Service
##############################################################

module "atlantis" {
source = "../../"

name = "atlantiscomplete"

# VPC
cidr = "10.20.0.0/16"
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.20.1.0/24", "10.20.2.0/24", "10.20.3.0/24"]
public_subnets = ["10.20.101.0/24", "10.20.102.0/24", "10.20.103.0/24"]

# ECS
ecs_container_insights = true
ecs_task_cpu = 512
ecs_task_memory = 1024
container_memory_reservation = 256

entrypoint = ["/bin/bash", "echo 'foo'", "docker-entrypoint.sh"]
command = ["server"]
working_directory = "/tmp"
docker_labels = {
"org.opencontainers.image.title" = "Atlantis"
"org.opencontainers.image.description" = "A self-hosted golang application that listens for Terraform pull request events via webhooks."
"org.opencontainers.image.url" = "https://github.com/runatlantis/atlantis/blob/master/Dockerfile"
}
start_timeout = 30
stop_timeout = 30

user = "atlantis"
readonly_root_filesystem = true
ulimits = [{
name = "nofile"
softLimit = 4096
hardLimit = 16384
}]

# DNS
route53_zone_name = var.domain

# Atlantis
atlantis_github_user = var.github_user
atlantis_github_user_token = var.github_token
atlantis_repo_whitelist = ["github.com/${var.github_organization}/*"]
atlantis_allowed_repo_names = var.allowed_repo_names

# ALB access
alb_ingress_cidr_blocks = [var.personal_ip]
alb_logging_enabled = true
alb_log_bucket_name = module.atlantis_access_log_bucket.this_s3_bucket_id
alb_log_location_prefix = "atlantis-alb"

allow_unauthenticated_access = true
allow_github_webhooks = true
allow_repo_config = true

tags = local.tags
}

################################################################################
# GitHub Webhooks
################################################################################

module "github_repository_webhook" {
source = "../../modules/github-repository-webhook"

github_organization = var.github_organization
github_token = var.github_token

atlantis_allowed_repo_names = module.atlantis.atlantis_allowed_repo_names

webhook_url = module.atlantis.atlantis_url_events
webhook_secret = module.atlantis.webhook_secret
}

################################################################################
# ALB Access Log Bucket + Policy
################################################################################

module "atlantis_access_log_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 1.9"

bucket = "${data.aws_caller_identity.current.account_id}-atlantis-access-logs-${data.aws_region.current.name}"
attach_policy = true
policy = data.aws_iam_policy_document.atlantis_access_log_bucket_policy.json

block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true

force_destroy = true

tags = local.tags

server_side_encryption_configuration = {
rule = {
apply_server_side_encryption_by_default = {
sse_algorithm = "AES256"
}
}
}

lifecycle_rule = [
{
id = "all"
enabled = true

transition = [
{
days = 30
storage_class = "ONEZONE_IA"
}, {
days = 60
storage_class = "GLACIER"
}
]

expiration = {
days = 90
}

noncurrent_version_expiration = {
days = 30
}
},
]
}

data "aws_iam_policy_document" "atlantis_access_log_bucket_policy" {
statement {
sid = "LogsLogDeliveryWrite"
effect = "Allow"
actions = ["s3:PutObject"]
resources = [
"${module.atlantis_access_log_bucket.this_s3_bucket_arn}/*/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
]

principals {
type = "AWS"
identifiers = [
# https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions
"arn:aws:iam::156460612806:root", # AWS logging eu-west-1 account id
]
}
}

statement {
sid = "AWSLogDeliveryWrite"
effect = "Allow"
actions = ["s3:PutObject"]
resources = [
"${module.atlantis_access_log_bucket.this_s3_bucket_arn}/*/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
]

principals {
type = "Service"
identifiers = [
"delivery.logs.amazonaws.com"
]
}

condition {
test = "StringEquals"
variable = "s3:x-amz-acl"

values = [
"bucket-owner-full-control"
]
}
}

statement {
sid = "AWSLogDeliveryAclCheck"
effect = "Allow"
actions = ["s3:GetBucketAcl"]
resources = [
module.atlantis_access_log_bucket.this_s3_bucket_arn
]

principals {
type = "Service"
identifiers = [
"delivery.logs.amazonaws.com"
]
}
}
}
31 changes: 31 additions & 0 deletions examples/github-complete/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Atlantis
output "atlantis_url" {
description = "URL of Atlantis"
value = module.atlantis.atlantis_url
}

output "atlantis_allowed_repo_names" {
description = "Git repositories where webhook should be created"
value = module.atlantis.atlantis_allowed_repo_names
}

output "task_role_arn" {
description = "The Atlantis ECS task role arn"
value = module.atlantis.task_role_arn
}

output "ecs_task_definition" {
description = "Task definition for ECS service (used for external triggers)"
value = module.atlantis.ecs_task_definition
}

# Webhooks
output "github_webhook_urls" {
description = "Github webhook URL"
value = module.github_repository_webhook.this_repository_webhook_urls
}

output "github_webhook_secret" {
description = "Github webhook secret"
value = module.github_repository_webhook.this_repository_webhook_secret
}
Loading