diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b7cf901..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -addons: - apt: - packages: - - git - - make - - curl - -install: - - make init - -script: - - make terraform/install - - make terraform/get-plugins - - make terraform/get-modules - - make terraform/lint - - make terraform/validate \ No newline at end of file diff --git a/README.md b/README.md index 84cdd20..a61948d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Cloud Posse][logo]](https://cpco.io/homepage) -# terraform-aws-ecs-atlantis [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-ecs-atlantis.svg?branch=master)](https://travis-ci.org/cloudposse/terraform-aws-ecs-atlantis) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-ecs-atlantis.svg)](https://github.com/cloudposse/terraform-aws-ecs-atlantis/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) +# terraform-aws-ecs-atlantis [![Codefresh Build Status](https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-ecs-atlantis?type=cf-1)](https://g.codefresh.io/public/accounts/cloudposse/pipelines/5dc082b14d7990012e651a3b) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-ecs-atlantis.svg)](https://github.com/cloudposse/terraform-aws-ecs-atlantis/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) ![terraform-aws-ecs-atlantis](docs/logo.png) @@ -143,11 +143,15 @@ Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest re -Module usage examples: +For a complete example, see [examples/complete](examples/complete). -- [without authentication](examples/without_authentication) - complete example without authentication -- [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication -- [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication +For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). + +Other examples: + +- [without authentication](examples/without_authentication) - example without authentication +- [with Google OIDC authentication](examples/with_google_oidc_authentication) - example with Google OIDC authentication +- [with Cognito authentication](examples/with_cognito_authentication) - example with Cognito authentication **NOTE:** @@ -156,39 +160,198 @@ Module usage examples: If no `github_webhooks_token` is set, [Terraform GitHub Provider](https://www.terraform.io/docs/providers/github/index.html) attempts to look one up in the `GITHUB_TOKEN` environment variable. -``` -module "atlantis" { - source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master" - enabled = "true" - name = "${var.name}" - namespace = "${var.namespace}" - region = "${var.region}" - stage = "${var.stage}" - - atlantis_gh_team_whitelist = "admins:*,engineering:plan" - atlantis_gh_user = "atlantis_bot" - atlantis_repo_whitelist = ["github.com/testing.example.co/*"] - - alb_arn_suffix = "${module.alb.alb_arn_suffix}" - alb_dns_name = "${module.alb.alb_dns_name}" - alb_name = "${module.alb.alb_name}" - alb_zone_id = "${module.alb.alb_zone_id}" - - domain_name = "${var.domain_name}" - ecs_cluster_arn = "${aws_ecs_cluster.default.arn}" - ecs_cluster_name = "${aws_ecs_cluster.default.name}" - repo_name = "testing.example.co" - repo_owner = "example_org" - private_subnet_ids = ["${module.subnets.private_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - vpc_id = "${module.vpc.vpc_id}" - - alb_ingress_unauthenticated_listener_arns = ["${module.alb.listener_arns}"] - alb_ingress_unauthenticated_listener_arns_count = 2 - alb_ingress_unauthenticated_paths = ["/*"] - alb_ingress_listener_unauthenticated_priority = "100" - alb_ingress_authenticated_paths = [] -} +```hcl + provider "aws" { + region = var.region + } + + module "label" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + } + + module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = var.vpc_cidr_block + tags = var.tags + } + + module "subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags + } + + module "alb" { + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + access_logs_enabled = false + alb_access_logs_s3_bucket_force_destroy = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags + } + + resource "aws_ecs_cluster" "default" { + name = module.label.id + tags = module.label.tags + } + + resource "aws_sns_topic" "sns_topic" { + name = module.label.id + display_name = "Test terraform-aws-ecs-atlantis" + tags = module.label.tags + } + + module "kms_key" { + source = "git::https://github.com/cloudposse/terraform-aws-kms-key.git?ref=tags/0.3.0" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + description = "Test terraform-aws-ecs-atlantis KMS key" + deletion_window_in_days = 7 + enable_key_rotation = false + } + + module "atlantis" { + source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + + region = var.region + vpc_id = module.vpc.vpc_id + policy_arn = var.policy_arn + ssh_private_key_name = var.ssh_private_key_name + ssh_public_key_name = var.ssh_public_key_name + kms_key_id = module.kms_key.key_id + + atlantis_gh_user = var.atlantis_gh_user + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_webhook_secret = var.atlantis_gh_webhook_secret + atlantis_log_level = var.atlantis_log_level + atlantis_repo_config = var.atlantis_repo_config + atlantis_repo_whitelist = var.atlantis_repo_whitelist + atlantis_port = var.atlantis_port + atlantis_webhook_format = var.atlantis_webhook_format + atlantis_url_format = var.atlantis_url_format + + default_backend_image = var.default_backend_image + healthcheck_path = var.healthcheck_path + short_name = var.short_name + hostname = var.hostname + parent_zone_id = var.parent_zone_id + + // Container + container_cpu = var.container_cpu + container_memory = var.container_memory + + // Authentication + authentication_type = var.authentication_type + alb_ingress_listener_unauthenticated_priority = var.alb_ingress_listener_unauthenticated_priority + alb_ingress_listener_authenticated_priority = var.alb_ingress_listener_authenticated_priority + alb_ingress_unauthenticated_hosts = var.alb_ingress_unauthenticated_hosts + alb_ingress_authenticated_hosts = var.alb_ingress_authenticated_hosts + alb_ingress_unauthenticated_paths = var.alb_ingress_unauthenticated_paths + alb_ingress_authenticated_paths = var.alb_ingress_authenticated_paths + authentication_cognito_user_pool_arn = var.authentication_cognito_user_pool_arn + authentication_cognito_user_pool_client_id = var.authentication_cognito_user_pool_client_id + authentication_cognito_user_pool_domain = var.authentication_cognito_user_pool_domain + authentication_oidc_client_id = var.authentication_oidc_client_id + authentication_oidc_client_secret = var.authentication_oidc_client_secret + authentication_oidc_issuer = var.authentication_oidc_issuer + authentication_oidc_authorization_endpoint = var.authentication_oidc_authorization_endpoint + authentication_oidc_token_endpoint = var.authentication_oidc_token_endpoint + authentication_oidc_user_info_endpoint = var.authentication_oidc_user_info_endpoint + + // ECS + private_subnet_ids = module.subnets.private_subnet_ids + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + security_group_ids = var.security_group_ids + desired_count = var.desired_count + launch_type = var.launch_type + + // ALB + alb_zone_id = module.alb.alb_zone_id + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_security_group = module.alb.security_group_id + alb_ingress_unauthenticated_listener_arns = [module.alb.http_listener_arn] + alb_ingress_unauthenticated_listener_arns_count = 1 + + // CodePipeline + codepipeline_enabled = var.codepipeline_enabled + github_oauth_token = var.github_oauth_token + github_webhooks_token = var.github_webhooks_token + repo_owner = var.repo_owner + repo_name = var.repo_name + branch = var.branch + build_timeout = var.build_timeout + webhook_enabled = var.webhook_enabled + webhook_secret_length = var.webhook_secret_length + webhook_events = var.webhook_events + codepipeline_s3_bucket_force_destroy = var.codepipeline_s3_bucket_force_destroy + + // Autoscaling + autoscaling_enabled = var.autoscaling_enabled + autoscaling_min_capacity = var.autoscaling_min_capacity + autoscaling_max_capacity = var.autoscaling_max_capacity + + // Alarms + alb_target_group_alarms_enabled = var.alb_target_group_alarms_enabled + ecs_alarms_enabled = var.ecs_alarms_enabled + alb_target_group_alarms_alarm_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_ok_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_insufficient_data_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] + } ``` @@ -212,33 +375,33 @@ Available targets: |------|-------------|:----:|:-----:|:-----:| | alb_arn_suffix | The ARN suffix of the ALB | string | - | yes | | alb_dns_name | DNS name of ALB | string | - | yes | -| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_authenticated_listener_arns | A list of authenticated ALB listener ARNs to attach ALB listener rules to | list | `` | no | -| alb_ingress_authenticated_listener_arns_count | The number of authenticated ARNs in `alb_ingress_authenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | string | `0` | no | -| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | string | `100` | no | -| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | string | `50` | no | -| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_unauthenticated_listener_arns | A list of unauthenticated ALB listener ARNs to attach ALB listener rules to | list | `` | no | -| alb_ingress_unauthenticated_listener_arns_count | The number of unauthenticated ARNs in `alb_ingress_unauthenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | string | `0` | no | -| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `` | no | -| alb_name | The Name of the ALB | string | - | yes | +| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_authenticated_listener_arns | A list of authenticated ALB listener ARNs to attach ALB listener rules to | list(string) | `` | no | +| alb_ingress_authenticated_listener_arns_count | The number of authenticated ARNs in `alb_ingress_authenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | number | `0` | no | +| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | number | `100` | no | +| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | number | `50` | no | +| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_unauthenticated_listener_arns | A list of unauthenticated ALB listener ARNs to attach ALB listener rules to | list(string) | `` | no | +| alb_ingress_unauthenticated_listener_arns_count | The number of unauthenticated ARNs in `alb_ingress_unauthenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | number | `0` | no | +| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list(string) | `` | no | | alb_security_group | Security group of the ALB | string | - | yes | -| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list | `` | no | -| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list | `` | no | -| alb_target_group_alarms_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an OK state from any other state. | list | `` | no | +| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list(string) | `` | no | +| alb_target_group_alarms_enabled | A boolean to enable/disable CloudWatch Alarms for ALB Target metrics | bool | `false` | no | +| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list(string) | `` | no | +| alb_target_group_alarms_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an OK state from any other state. | list(string) | `` | no | | alb_zone_id | The ID of the zone in which ALB is provisioned | string | - | yes | | atlantis_gh_team_whitelist | Atlantis GitHub team whitelist | string | `` | no | | atlantis_gh_user | Atlantis GitHub user | string | - | yes | | atlantis_gh_webhook_secret | Atlantis GitHub webhook secret | string | `` | no | | atlantis_log_level | Atlantis log level | string | `info` | no | -| atlantis_port | Atlantis container port | string | `4141` | no | +| atlantis_port | Atlantis container port | number | `4141` | no | | atlantis_repo_config | Path to atlantis server-side repo config file (https://www.runatlantis.io/docs/server-side-repo-config.html) | string | `atlantis-repo-config.yaml` | no | -| atlantis_repo_whitelist | Whitelist of repositories Atlantis will accept webhooks from | list | `` | no | +| atlantis_repo_whitelist | Whitelist of repositories Atlantis will accept webhooks from | list(string) | `` | no | | atlantis_url_format | Template for the Atlantis URL which is populated with the hostname | string | `https://%s` | no | -| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no | +| atlantis_wake_word | Wake world for atlantis | string | `atlantis` | no | | atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no | -| attributes | Additional attributes (e.g. `1`) | list | `` | no | +| attributes | Additional attributes (_e.g._ "1") | list(string) | `` | no | | authentication_cognito_user_pool_arn | Cognito User Pool ARN | string | `` | no | | authentication_cognito_user_pool_arn_ssm_name | SSM param name to lookup `authentication_cognito_user_pool_arn` if not provided | string | `` | no | | authentication_cognito_user_pool_client_id | Cognito User Pool Client ID | string | `` | no | @@ -254,21 +417,32 @@ Available targets: | authentication_oidc_token_endpoint | OIDC Token Endpoint | string | `` | no | | authentication_oidc_user_info_endpoint | OIDC User Info Endpoint | string | `` | no | | authentication_type | Authentication type. Supported values are `COGNITO` and `OIDC` | string | `` | no | -| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no | -| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no | +| autoscaling_enabled | A boolean to enable/disable Autoscaling policy for ECS Service | bool | `false` | no | +| autoscaling_max_capacity | Atlantis maximum tasks to run | number | `1` | no | +| autoscaling_min_capacity | Atlantis minimum tasks to run | number | `1` | no | | branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no | -| build_timeout | How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. | string | `5` | no | +| build_timeout | How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. | number | `10` | no | | chamber_format | Format to store parameters in SSM, for consumption with chamber | string | `/%s/%s` | no | | chamber_service | SSM parameter service name for use with chamber. This is used in chamber_format where /$chamber_service/$parameter would be the default. | string | `atlantis` | no | -| codepipeline_s3_bucket_force_destroy | A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error | string | `false` | no | -| container_cpu | Atlantis CPUs per task | string | `256` | no | -| container_memory | Atlantis memory per task | string | `512` | no | +| codepipeline_enabled | A boolean to enable/disable AWS Codepipeline and ECR | bool | `false` | no | +| codepipeline_s3_bucket_force_destroy | A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error | bool | `false` | no | +| container_cpu | Atlantis CPUs per task | number | `256` | no | +| container_memory | Atlantis memory per task | number | `512` | no | | default_backend_image | ECS default (bootstrap) image | string | `cloudposse/default-backend:0.1.2` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | -| desired_count | Atlantis desired number of tasks | string | `1` | no | +| delimiter | Delimiter between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | +| desired_count | Atlantis desired number of tasks | number | `1` | no | +| ecs_alarms_cpu_utilization_high_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High Alarm action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_high_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High OK action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_low_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low Alarm action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_low_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low OK action | list(string) | `` | no | +| ecs_alarms_enabled | A boolean to enable/disable CloudWatch Alarms for ECS Service metrics | bool | `false` | no | +| ecs_alarms_memory_utilization_high_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High Alarm action | list(string) | `` | no | +| ecs_alarms_memory_utilization_high_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High OK action | list(string) | `` | no | +| ecs_alarms_memory_utilization_low_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low Alarm action | list(string) | `` | no | +| ecs_alarms_memory_utilization_low_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low OK action | list(string) | `` | no | | ecs_cluster_arn | ARN of the ECS cluster to deploy Atlantis | string | - | yes | | ecs_cluster_name | Name of the ECS cluster to deploy Atlantis | string | - | yes | -| enabled | Whether to create the resources. Set to `false` to prevent the module from creating any resources | string | `false` | no | +| enabled | Whether to create the resources. Set to `false` to prevent the module from creating any resources | bool | `false` | no | | github_oauth_token | GitHub OAuth token. If not provided the token is looked up from SSM | string | `` | no | | github_oauth_token_ssm_name | SSM param name to lookup `github_oauth_token` if not provided | string | `` | no | | github_webhooks_token | GitHub OAuth Token with permissions to create webhooks. If not provided the token is looked up from SSM | string | `` | no | @@ -276,33 +450,85 @@ Available targets: | healthcheck_path | Healthcheck path | string | `/healthz` | no | | hostname | Atlantis URL | string | `` | no | | kms_key_id | KMS key ID used to encrypt SSM SecureString parameters | string | `` | no | -| name | Application or solution name (e.g. `app`) | string | `ecs` | no | -| namespace | Namespace (e.g. `eg` or `cp`) | string | - | yes | -| overwrite_ssm_parameter | Whether to overwrite an existing SSM parameter | string | `true` | no | +| launch_type | The ECS launch type (valid options: FARGATE or EC2) | string | `FARGATE` | no | +| name | Name of the application | string | - | yes | +| namespace | Namespace (e.g. `eg` or `cp`) | string | `` | no | +| overwrite_ssm_parameter | Whether to overwrite an existing SSM parameter | bool | `true` | no | | parent_zone_id | The zone ID where the DNS record for the `short_name` will be written | string | `` | no | | policy_arn | Permission to grant to atlantis server | string | `arn:aws:iam::aws:policy/AdministratorAccess` | no | -| private_subnet_ids | The private subnet IDs | list | `` | no | -| region | AWS Region for Atlantis deployment | string | `us-west-2` | no | +| private_subnet_ids | The private subnet IDs | list(string) | `` | no | +| region | AWS Region for S3 bucket | string | - | yes | | repo_name | GitHub repository name of the atlantis to be built and deployed to ECS. | string | - | yes | | repo_owner | GitHub organization containing the Atlantis repository | string | - | yes | -| security_group_ids | Additional Security Group IDs to allow into ECS Service. | list | `` | no | -| short_name | Alantis Short DNS name (E.g. `atlantis`) | string | `atlantis` | no | +| security_group_ids | Additional Security Group IDs to allow into ECS Service. | list(string) | `` | no | +| short_name | Alantis short DNS name (e.g. `atlantis`) | string | `atlantis` | no | | ssh_private_key_name | Atlantis SSH private key name | string | `atlantis_ssh_private_key` | no | | ssh_public_key_name | Atlantis SSH public key name | string | `atlantis_ssh_public_key` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | - | yes | -| tags | Additional tags (e.g. map(`BusinessUnit`,`XYZ`) | map | `` | no | +| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | `` | no | +| tags | Additional tags (_e.g._ { BusinessUnit : ABC }) | map(string) | `` | no | | vpc_id | VPC ID for the ECS Cluster | string | - | yes | -| webhook_events | A list of events which should trigger the webhook. | list | `` | no | -| webhook_secret_length | GitHub webhook secret length | string | `32` | no | +| webhook_enabled | Set to false to prevent the module from creating any webhook resources | bool | `true` | no | +| webhook_events | A list of events which should trigger the webhook. | list(string) | `` | no | +| webhook_secret_length | GitHub webhook secret length | number | `32` | no | ## Outputs | Name | Description | |------|-------------| +| alb_ingress_target_group_arn | ALB Target Group ARN | +| alb_ingress_target_group_arn_suffix | ALB Target Group ARN suffix | +| alb_ingress_target_group_name | ALB Target Group name | | atlantis_ssh_public_key | Atlantis SSH Public Key | | atlantis_url | The URL endpoint for the atlantis server | | atlantis_webhook_url | atlantis webhook URL | -| badge_url | The URL of the build badge when `badge_enabled` is enabled | +| codebuild_badge_url | The URL of the build badge when badge_enabled is enabled | +| codebuild_cache_bucket_arn | CodeBuild cache S3 bucket ARN | +| codebuild_cache_bucket_name | CodeBuild cache S3 bucket name | +| codebuild_project_id | CodeBuild project ID | +| codebuild_project_name | CodeBuild project name | +| codebuild_role_arn | CodeBuild IAM Role ARN | +| codebuild_role_id | CodeBuild IAM Role ID | +| codepipeline_arn | CodePipeline ARN | +| codepipeline_id | CodePipeline ID | +| codepipeline_webhook_id | The CodePipeline webhook's ID | +| codepipeline_webhook_url | The CodePipeline webhook's URL. POST events to this endpoint to trigger the target | +| 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 | JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition | +| ecr_registry_id | Registry ID | +| ecr_registry_url | Registry URL | +| ecr_repository_name | Registry name | +| ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn | ECS CPU utilization high CloudWatch metric alarm ARN | +| ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id | ECS CPU utilization high CloudWatch metric alarm ID | +| ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn | ECS CPU utilization low CloudWatch metric alarm ARN | +| ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id | ECS CPU utilization low CloudWatch metric alarm ID | +| ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn | ECS Memory utilization high CloudWatch metric alarm ARN | +| ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id | ECS Memory utilization high CloudWatch metric alarm ID | +| ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn | ECS Memory utilization low CloudWatch metric alarm ARN | +| ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id | ECS Memory utilization low CloudWatch metric alarm ID | +| ecs_cloudwatch_autoscaling_scale_down_policy_arn | ARN of the scale down policy | +| ecs_cloudwatch_autoscaling_scale_up_policy_arn | ARN of the scale up policy | +| 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 | ECS service role name | +| ecs_service_name | ECS Service name | +| ecs_service_role_arn | ECS Service role ARN | +| ecs_service_security_group_id | Security Group ID of the ECS task | +| ecs_task_definition_family | ECS task definition family | +| ecs_task_definition_revision | ECS task definition revision | +| ecs_task_exec_role_arn | ECS Task exec role ARN | +| ecs_task_exec_role_name | ECS Task role name | +| ecs_task_role_arn | ECS Task role ARN | +| ecs_task_role_id | ECS Task role id | +| ecs_task_role_name | ECS Task role name | +| httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn | ALB 5xx count CloudWatch metric alarm ARN | +| httpcode_elb_5xx_count_cloudwatch_metric_alarm_id | ALB 5xx count CloudWatch metric alarm ID | +| httpcode_target_3xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 3xx count CloudWatch metric alarm ARN | +| httpcode_target_3xx_count_cloudwatch_metric_alarm_id | ALB Target Group 3xx count CloudWatch metric alarm ID | +| httpcode_target_4xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 4xx count CloudWatch metric alarm ARN | +| httpcode_target_4xx_count_cloudwatch_metric_alarm_id | ALB Target Group 4xx count CloudWatch metric alarm ID | +| httpcode_target_5xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 5xx count CloudWatch metric alarm ARN | +| httpcode_target_5xx_count_cloudwatch_metric_alarm_id | ALB Target Group 5xx count CloudWatch metric alarm ID | +| target_response_time_average_cloudwatch_metric_alarm_arn | ALB Target Group response time average CloudWatch metric alarm ARN | +| target_response_time_average_cloudwatch_metric_alarm_id | ALB Target Group response time average CloudWatch metric alarm ID | @@ -459,13 +685,13 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply |---|---|---|---| [joshmyers_homepage]: https://github.com/joshmyers - [joshmyers_avatar]: https://github.com/joshmyers.png?size=150 + [joshmyers_avatar]: https://img.cloudposse.com/150x150/https://github.com/joshmyers.png [osterman_homepage]: https://github.com/osterman - [osterman_avatar]: https://github.com/osterman.png?size=150 + [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png [aknysh_homepage]: https://github.com/aknysh - [aknysh_avatar]: https://github.com/aknysh.png?size=150 + [aknysh_avatar]: https://img.cloudposse.com/150x150/https://github.com/aknysh.png [goruha_homepage]: https://github.com/goruha - [goruha_avatar]: https://github.com/goruha.png?size=150 + [goruha_avatar]: https://img.cloudposse.com/150x150/https://github.com/goruha.png diff --git a/README.yaml b/README.yaml index ca25fb1..a6653a7 100644 --- a/README.yaml +++ b/README.yaml @@ -24,9 +24,9 @@ screenshots: # Badges to display badges: - - name: "Build Status" - image: "https://travis-ci.org/cloudposse/terraform-aws-ecs-atlantis.svg?branch=master" - url: "https://travis-ci.org/cloudposse/terraform-aws-ecs-atlantis" + - name: "Codefresh Build Status" + image: "https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-ecs-atlantis?type=cf-1" + url: "https://g.codefresh.io/public/accounts/cloudposse/pipelines/5dc082b14d7990012e651a3b" - name: "Latest Release" image: "https://img.shields.io/github/release/cloudposse/terraform-aws-ecs-atlantis.svg" url: "https://github.com/cloudposse/terraform-aws-ecs-atlantis/releases/latest" @@ -159,11 +159,15 @@ introduction: |- # How to use this project usage: |- - Module usage examples: + For a complete example, see [examples/complete](examples/complete). - - [without authentication](examples/without_authentication) - complete example without authentication - - [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication - - [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication + For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test). + + Other examples: + + - [without authentication](examples/without_authentication) - example without authentication + - [with Google OIDC authentication](examples/with_google_oidc_authentication) - example with Google OIDC authentication + - [with Cognito authentication](examples/with_cognito_authentication) - example with Cognito authentication **NOTE:** @@ -172,39 +176,198 @@ usage: |- If no `github_webhooks_token` is set, [Terraform GitHub Provider](https://www.terraform.io/docs/providers/github/index.html) attempts to look one up in the `GITHUB_TOKEN` environment variable. - ``` - module "atlantis" { - source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master" - enabled = "true" - name = "${var.name}" - namespace = "${var.namespace}" - region = "${var.region}" - stage = "${var.stage}" - - atlantis_gh_team_whitelist = "admins:*,engineering:plan" - atlantis_gh_user = "atlantis_bot" - atlantis_repo_whitelist = ["github.com/testing.example.co/*"] - - alb_arn_suffix = "${module.alb.alb_arn_suffix}" - alb_dns_name = "${module.alb.alb_dns_name}" - alb_name = "${module.alb.alb_name}" - alb_zone_id = "${module.alb.alb_zone_id}" - - domain_name = "${var.domain_name}" - ecs_cluster_arn = "${aws_ecs_cluster.default.arn}" - ecs_cluster_name = "${aws_ecs_cluster.default.name}" - repo_name = "testing.example.co" - repo_owner = "example_org" - private_subnet_ids = ["${module.subnets.private_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - vpc_id = "${module.vpc.vpc_id}" - - alb_ingress_unauthenticated_listener_arns = ["${module.alb.listener_arns}"] - alb_ingress_unauthenticated_listener_arns_count = 2 - alb_ingress_unauthenticated_paths = ["/*"] - alb_ingress_listener_unauthenticated_priority = "100" - alb_ingress_authenticated_paths = [] - } + ```hcl + provider "aws" { + region = var.region + } + + module "label" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + } + + module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = var.vpc_cidr_block + tags = var.tags + } + + module "subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags + } + + module "alb" { + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + access_logs_enabled = false + alb_access_logs_s3_bucket_force_destroy = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags + } + + resource "aws_ecs_cluster" "default" { + name = module.label.id + tags = module.label.tags + } + + resource "aws_sns_topic" "sns_topic" { + name = module.label.id + display_name = "Test terraform-aws-ecs-atlantis" + tags = module.label.tags + } + + module "kms_key" { + source = "git::https://github.com/cloudposse/terraform-aws-kms-key.git?ref=tags/0.3.0" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + description = "Test terraform-aws-ecs-atlantis KMS key" + deletion_window_in_days = 7 + enable_key_rotation = false + } + + module "atlantis" { + source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + + region = var.region + vpc_id = module.vpc.vpc_id + policy_arn = var.policy_arn + ssh_private_key_name = var.ssh_private_key_name + ssh_public_key_name = var.ssh_public_key_name + kms_key_id = module.kms_key.key_id + + atlantis_gh_user = var.atlantis_gh_user + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_webhook_secret = var.atlantis_gh_webhook_secret + atlantis_log_level = var.atlantis_log_level + atlantis_repo_config = var.atlantis_repo_config + atlantis_repo_whitelist = var.atlantis_repo_whitelist + atlantis_port = var.atlantis_port + atlantis_webhook_format = var.atlantis_webhook_format + atlantis_url_format = var.atlantis_url_format + + default_backend_image = var.default_backend_image + healthcheck_path = var.healthcheck_path + short_name = var.short_name + hostname = var.hostname + parent_zone_id = var.parent_zone_id + + // Container + container_cpu = var.container_cpu + container_memory = var.container_memory + + // Authentication + authentication_type = var.authentication_type + alb_ingress_listener_unauthenticated_priority = var.alb_ingress_listener_unauthenticated_priority + alb_ingress_listener_authenticated_priority = var.alb_ingress_listener_authenticated_priority + alb_ingress_unauthenticated_hosts = var.alb_ingress_unauthenticated_hosts + alb_ingress_authenticated_hosts = var.alb_ingress_authenticated_hosts + alb_ingress_unauthenticated_paths = var.alb_ingress_unauthenticated_paths + alb_ingress_authenticated_paths = var.alb_ingress_authenticated_paths + authentication_cognito_user_pool_arn = var.authentication_cognito_user_pool_arn + authentication_cognito_user_pool_client_id = var.authentication_cognito_user_pool_client_id + authentication_cognito_user_pool_domain = var.authentication_cognito_user_pool_domain + authentication_oidc_client_id = var.authentication_oidc_client_id + authentication_oidc_client_secret = var.authentication_oidc_client_secret + authentication_oidc_issuer = var.authentication_oidc_issuer + authentication_oidc_authorization_endpoint = var.authentication_oidc_authorization_endpoint + authentication_oidc_token_endpoint = var.authentication_oidc_token_endpoint + authentication_oidc_user_info_endpoint = var.authentication_oidc_user_info_endpoint + + // ECS + private_subnet_ids = module.subnets.private_subnet_ids + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + security_group_ids = var.security_group_ids + desired_count = var.desired_count + launch_type = var.launch_type + + // ALB + alb_zone_id = module.alb.alb_zone_id + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_security_group = module.alb.security_group_id + alb_ingress_unauthenticated_listener_arns = [module.alb.http_listener_arn] + alb_ingress_unauthenticated_listener_arns_count = 1 + + // CodePipeline + codepipeline_enabled = var.codepipeline_enabled + github_oauth_token = var.github_oauth_token + github_webhooks_token = var.github_webhooks_token + repo_owner = var.repo_owner + repo_name = var.repo_name + branch = var.branch + build_timeout = var.build_timeout + webhook_enabled = var.webhook_enabled + webhook_secret_length = var.webhook_secret_length + webhook_events = var.webhook_events + codepipeline_s3_bucket_force_destroy = var.codepipeline_s3_bucket_force_destroy + + // Autoscaling + autoscaling_enabled = var.autoscaling_enabled + autoscaling_min_capacity = var.autoscaling_min_capacity + autoscaling_max_capacity = var.autoscaling_max_capacity + + // Alarms + alb_target_group_alarms_enabled = var.alb_target_group_alarms_enabled + ecs_alarms_enabled = var.ecs_alarms_enabled + alb_target_group_alarms_alarm_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_ok_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_insufficient_data_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] + } ``` # Example usage diff --git a/codefresh/test.yml b/codefresh/test.yml new file mode 100644 index 0000000..ddd07f9 --- /dev/null +++ b/codefresh/test.yml @@ -0,0 +1,74 @@ +version: '1.0' + +stages: + - Prepare + - Test + +steps: + wait: + title: Wait + stage: Prepare + image: codefresh/cli:latest + commands: + - codefresh get builds --pipeline=${{CF_REPO_NAME}} --status running --limit 1000 -o json | jq --arg id ${{CF_BUILD_ID}} -ser 'flatten|.[-1].id==$id' + retry: + maxAttempts: 10 + delay: 20 + exponentialFactor: 1.1 + + main_clone: + title: "Clone repository" + type: git-clone + stage: Prepare + description: "Initialize" + repo: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + git: CF-default + revision: ${{CF_REVISION}} + + clean_init: + title: Prepare build-harness and test-harness + image: ${{TEST_IMAGE}} + stage: Prepare + commands: + - cf_export PATH="/usr/local/terraform/0.12/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + - make init + - git -C build-harness checkout master + - make -C test/ clean init TEST_HARNESS_BRANCH=master + - make -C test/src clean init + - find . -type d -name '.terraform' | xargs rm -rf + - find . -type f -name 'terraform.tfstate*' -exec rm -f {} \; + + test: + type: "parallel" + title: "Run tests" + description: "Run all tests in parallel" + stage: Test + steps: + test_readme_lint: + title: "Test README.md updated" + stage: "Test" + image: ${{TEST_IMAGE}} + description: Test "readme/lint" + commands: + - make readme/lint + + test_module: + title: Test module with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ module + + test_examples_complete: + title: Test "examples/complete" with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ examples/complete + + test_examples_complete_terratest: + title: Test "examples/complete" with terratest + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/src diff --git a/docs/terraform.md b/docs/terraform.md index 86d8834..0583d16 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -4,33 +4,33 @@ |------|-------------|:----:|:-----:|:-----:| | alb_arn_suffix | The ARN suffix of the ALB | string | - | yes | | alb_dns_name | DNS name of ALB | string | - | yes | -| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_authenticated_listener_arns | A list of authenticated ALB listener ARNs to attach ALB listener rules to | list | `` | no | -| alb_ingress_authenticated_listener_arns_count | The number of authenticated ARNs in `alb_ingress_authenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | string | `0` | no | -| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | string | `100` | no | -| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | string | `50` | no | -| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `` | no | -| alb_ingress_unauthenticated_listener_arns | A list of unauthenticated ALB listener ARNs to attach ALB listener rules to | list | `` | no | -| alb_ingress_unauthenticated_listener_arns_count | The number of unauthenticated ARNs in `alb_ingress_unauthenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | string | `0` | no | -| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `` | no | -| alb_name | The Name of the ALB | string | - | yes | +| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_authenticated_listener_arns | A list of authenticated ALB listener ARNs to attach ALB listener rules to | list(string) | `` | no | +| alb_ingress_authenticated_listener_arns_count | The number of authenticated ARNs in `alb_ingress_authenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | number | `0` | no | +| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | number | `100` | no | +| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | number | `50` | no | +| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list(string) | `` | no | +| alb_ingress_unauthenticated_listener_arns | A list of unauthenticated ALB listener ARNs to attach ALB listener rules to | list(string) | `` | no | +| alb_ingress_unauthenticated_listener_arns_count | The number of unauthenticated ARNs in `alb_ingress_unauthenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed | number | `0` | no | +| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list(string) | `` | no | | alb_security_group | Security group of the ALB | string | - | yes | -| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list | `` | no | -| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list | `` | no | -| alb_target_group_alarms_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an OK state from any other state. | list | `` | no | +| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list(string) | `` | no | +| alb_target_group_alarms_enabled | A boolean to enable/disable CloudWatch Alarms for ALB Target metrics | bool | `false` | no | +| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list(string) | `` | no | +| alb_target_group_alarms_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an OK state from any other state. | list(string) | `` | no | | alb_zone_id | The ID of the zone in which ALB is provisioned | string | - | yes | | atlantis_gh_team_whitelist | Atlantis GitHub team whitelist | string | `` | no | | atlantis_gh_user | Atlantis GitHub user | string | - | yes | | atlantis_gh_webhook_secret | Atlantis GitHub webhook secret | string | `` | no | | atlantis_log_level | Atlantis log level | string | `info` | no | -| atlantis_port | Atlantis container port | string | `4141` | no | +| atlantis_port | Atlantis container port | number | `4141` | no | | atlantis_repo_config | Path to atlantis server-side repo config file (https://www.runatlantis.io/docs/server-side-repo-config.html) | string | `atlantis-repo-config.yaml` | no | -| atlantis_repo_whitelist | Whitelist of repositories Atlantis will accept webhooks from | list | `` | no | +| atlantis_repo_whitelist | Whitelist of repositories Atlantis will accept webhooks from | list(string) | `` | no | | atlantis_url_format | Template for the Atlantis URL which is populated with the hostname | string | `https://%s` | no | -| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no | +| atlantis_wake_word | Wake world for atlantis | string | `atlantis` | no | | atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no | -| attributes | Additional attributes (e.g. `1`) | list | `` | no | +| attributes | Additional attributes (_e.g._ "1") | list(string) | `` | no | | authentication_cognito_user_pool_arn | Cognito User Pool ARN | string | `` | no | | authentication_cognito_user_pool_arn_ssm_name | SSM param name to lookup `authentication_cognito_user_pool_arn` if not provided | string | `` | no | | authentication_cognito_user_pool_client_id | Cognito User Pool Client ID | string | `` | no | @@ -46,21 +46,32 @@ | authentication_oidc_token_endpoint | OIDC Token Endpoint | string | `` | no | | authentication_oidc_user_info_endpoint | OIDC User Info Endpoint | string | `` | no | | authentication_type | Authentication type. Supported values are `COGNITO` and `OIDC` | string | `` | no | -| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no | -| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no | +| autoscaling_enabled | A boolean to enable/disable Autoscaling policy for ECS Service | bool | `false` | no | +| autoscaling_max_capacity | Atlantis maximum tasks to run | number | `1` | no | +| autoscaling_min_capacity | Atlantis minimum tasks to run | number | `1` | no | | branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no | -| build_timeout | How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. | string | `5` | no | +| build_timeout | How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. | number | `10` | no | | chamber_format | Format to store parameters in SSM, for consumption with chamber | string | `/%s/%s` | no | | chamber_service | SSM parameter service name for use with chamber. This is used in chamber_format where /$chamber_service/$parameter would be the default. | string | `atlantis` | no | -| codepipeline_s3_bucket_force_destroy | A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error | string | `false` | no | -| container_cpu | Atlantis CPUs per task | string | `256` | no | -| container_memory | Atlantis memory per task | string | `512` | no | +| codepipeline_enabled | A boolean to enable/disable AWS Codepipeline and ECR | bool | `false` | no | +| codepipeline_s3_bucket_force_destroy | A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error | bool | `false` | no | +| container_cpu | Atlantis CPUs per task | number | `256` | no | +| container_memory | Atlantis memory per task | number | `512` | no | | default_backend_image | ECS default (bootstrap) image | string | `cloudposse/default-backend:0.1.2` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | -| desired_count | Atlantis desired number of tasks | string | `1` | no | +| delimiter | Delimiter between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | +| desired_count | Atlantis desired number of tasks | number | `1` | no | +| ecs_alarms_cpu_utilization_high_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High Alarm action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_high_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High OK action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_low_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low Alarm action | list(string) | `` | no | +| ecs_alarms_cpu_utilization_low_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low OK action | list(string) | `` | no | +| ecs_alarms_enabled | A boolean to enable/disable CloudWatch Alarms for ECS Service metrics | bool | `false` | no | +| ecs_alarms_memory_utilization_high_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High Alarm action | list(string) | `` | no | +| ecs_alarms_memory_utilization_high_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High OK action | list(string) | `` | no | +| ecs_alarms_memory_utilization_low_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low Alarm action | list(string) | `` | no | +| ecs_alarms_memory_utilization_low_ok_actions | A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low OK action | list(string) | `` | no | | ecs_cluster_arn | ARN of the ECS cluster to deploy Atlantis | string | - | yes | | ecs_cluster_name | Name of the ECS cluster to deploy Atlantis | string | - | yes | -| enabled | Whether to create the resources. Set to `false` to prevent the module from creating any resources | string | `false` | no | +| enabled | Whether to create the resources. Set to `false` to prevent the module from creating any resources | bool | `false` | no | | github_oauth_token | GitHub OAuth token. If not provided the token is looked up from SSM | string | `` | no | | github_oauth_token_ssm_name | SSM param name to lookup `github_oauth_token` if not provided | string | `` | no | | github_webhooks_token | GitHub OAuth Token with permissions to create webhooks. If not provided the token is looked up from SSM | string | `` | no | @@ -68,31 +79,83 @@ | healthcheck_path | Healthcheck path | string | `/healthz` | no | | hostname | Atlantis URL | string | `` | no | | kms_key_id | KMS key ID used to encrypt SSM SecureString parameters | string | `` | no | -| name | Application or solution name (e.g. `app`) | string | `ecs` | no | -| namespace | Namespace (e.g. `eg` or `cp`) | string | - | yes | -| overwrite_ssm_parameter | Whether to overwrite an existing SSM parameter | string | `true` | no | +| launch_type | The ECS launch type (valid options: FARGATE or EC2) | string | `FARGATE` | no | +| name | Name of the application | string | - | yes | +| namespace | Namespace (e.g. `eg` or `cp`) | string | `` | no | +| overwrite_ssm_parameter | Whether to overwrite an existing SSM parameter | bool | `true` | no | | parent_zone_id | The zone ID where the DNS record for the `short_name` will be written | string | `` | no | | policy_arn | Permission to grant to atlantis server | string | `arn:aws:iam::aws:policy/AdministratorAccess` | no | -| private_subnet_ids | The private subnet IDs | list | `` | no | -| region | AWS Region for Atlantis deployment | string | `us-west-2` | no | +| private_subnet_ids | The private subnet IDs | list(string) | `` | no | +| region | AWS Region for S3 bucket | string | - | yes | | repo_name | GitHub repository name of the atlantis to be built and deployed to ECS. | string | - | yes | | repo_owner | GitHub organization containing the Atlantis repository | string | - | yes | -| security_group_ids | Additional Security Group IDs to allow into ECS Service. | list | `` | no | -| short_name | Alantis Short DNS name (E.g. `atlantis`) | string | `atlantis` | no | +| security_group_ids | Additional Security Group IDs to allow into ECS Service. | list(string) | `` | no | +| short_name | Alantis short DNS name (e.g. `atlantis`) | string | `atlantis` | no | | ssh_private_key_name | Atlantis SSH private key name | string | `atlantis_ssh_private_key` | no | | ssh_public_key_name | Atlantis SSH public key name | string | `atlantis_ssh_public_key` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | - | yes | -| tags | Additional tags (e.g. map(`BusinessUnit`,`XYZ`) | map | `` | no | +| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | `` | no | +| tags | Additional tags (_e.g._ { BusinessUnit : ABC }) | map(string) | `` | no | | vpc_id | VPC ID for the ECS Cluster | string | - | yes | -| webhook_events | A list of events which should trigger the webhook. | list | `` | no | -| webhook_secret_length | GitHub webhook secret length | string | `32` | no | +| webhook_enabled | Set to false to prevent the module from creating any webhook resources | bool | `true` | no | +| webhook_events | A list of events which should trigger the webhook. | list(string) | `` | no | +| webhook_secret_length | GitHub webhook secret length | number | `32` | no | ## Outputs | Name | Description | |------|-------------| +| alb_ingress_target_group_arn | ALB Target Group ARN | +| alb_ingress_target_group_arn_suffix | ALB Target Group ARN suffix | +| alb_ingress_target_group_name | ALB Target Group name | | atlantis_ssh_public_key | Atlantis SSH Public Key | | atlantis_url | The URL endpoint for the atlantis server | | atlantis_webhook_url | atlantis webhook URL | -| badge_url | The URL of the build badge when `badge_enabled` is enabled | +| codebuild_badge_url | The URL of the build badge when badge_enabled is enabled | +| codebuild_cache_bucket_arn | CodeBuild cache S3 bucket ARN | +| codebuild_cache_bucket_name | CodeBuild cache S3 bucket name | +| codebuild_project_id | CodeBuild project ID | +| codebuild_project_name | CodeBuild project name | +| codebuild_role_arn | CodeBuild IAM Role ARN | +| codebuild_role_id | CodeBuild IAM Role ID | +| codepipeline_arn | CodePipeline ARN | +| codepipeline_id | CodePipeline ID | +| codepipeline_webhook_id | The CodePipeline webhook's ID | +| codepipeline_webhook_url | The CodePipeline webhook's URL. POST events to this endpoint to trigger the target | +| 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 | JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition | +| ecr_registry_id | Registry ID | +| ecr_registry_url | Registry URL | +| ecr_repository_name | Registry name | +| ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn | ECS CPU utilization high CloudWatch metric alarm ARN | +| ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id | ECS CPU utilization high CloudWatch metric alarm ID | +| ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn | ECS CPU utilization low CloudWatch metric alarm ARN | +| ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id | ECS CPU utilization low CloudWatch metric alarm ID | +| ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn | ECS Memory utilization high CloudWatch metric alarm ARN | +| ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id | ECS Memory utilization high CloudWatch metric alarm ID | +| ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn | ECS Memory utilization low CloudWatch metric alarm ARN | +| ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id | ECS Memory utilization low CloudWatch metric alarm ID | +| ecs_cloudwatch_autoscaling_scale_down_policy_arn | ARN of the scale down policy | +| ecs_cloudwatch_autoscaling_scale_up_policy_arn | ARN of the scale up policy | +| 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 | ECS service role name | +| ecs_service_name | ECS Service name | +| ecs_service_role_arn | ECS Service role ARN | +| ecs_service_security_group_id | Security Group ID of the ECS task | +| ecs_task_definition_family | ECS task definition family | +| ecs_task_definition_revision | ECS task definition revision | +| ecs_task_exec_role_arn | ECS Task exec role ARN | +| ecs_task_exec_role_name | ECS Task role name | +| ecs_task_role_arn | ECS Task role ARN | +| ecs_task_role_id | ECS Task role id | +| ecs_task_role_name | ECS Task role name | +| httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn | ALB 5xx count CloudWatch metric alarm ARN | +| httpcode_elb_5xx_count_cloudwatch_metric_alarm_id | ALB 5xx count CloudWatch metric alarm ID | +| httpcode_target_3xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 3xx count CloudWatch metric alarm ARN | +| httpcode_target_3xx_count_cloudwatch_metric_alarm_id | ALB Target Group 3xx count CloudWatch metric alarm ID | +| httpcode_target_4xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 4xx count CloudWatch metric alarm ARN | +| httpcode_target_4xx_count_cloudwatch_metric_alarm_id | ALB Target Group 4xx count CloudWatch metric alarm ID | +| httpcode_target_5xx_count_cloudwatch_metric_alarm_arn | ALB Target Group 5xx count CloudWatch metric alarm ARN | +| httpcode_target_5xx_count_cloudwatch_metric_alarm_id | ALB Target Group 5xx count CloudWatch metric alarm ID | +| target_response_time_average_cloudwatch_metric_alarm_arn | ALB Target Group response time average CloudWatch metric alarm ARN | +| target_response_time_average_cloudwatch_metric_alarm_id | ALB Target Group response time average CloudWatch metric alarm ID | diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars new file mode 100644 index 0000000..4a7b476 --- /dev/null +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -0,0 +1,69 @@ +enabled = true + +region = "us-east-2" + +availability_zones = ["us-east-2a", "us-east-2b"] + +namespace = "eg" + +stage = "test" + +name = "ecs-atlantis" + +vpc_cidr_block = "172.16.0.0/16" + +container_cpu = 256 + +container_memory = 512 + +desired_count = 1 + +launch_type = "FARGATE" + +authentication_type = "" + +alb_ingress_listener_unauthenticated_priority = 1000 + +alb_ingress_unauthenticated_paths = ["/"] + +autoscaling_enabled = true + +autoscaling_min_capacity = 1 + +autoscaling_max_capacity = 2 + +webhook_enabled = false + +github_oauth_token = "test" + +github_webhooks_token = "test" + +atlantis_gh_user = "test" + +atlantis_gh_team_whitelist = "dev:plan,ops:*" + +atlantis_repo_whitelist = ["cloudposse/terraform-aws-ecs-atlantis"] + +codepipeline_enabled = true + +codepipeline_s3_bucket_force_destroy = true + +build_timeout = 20 + +repo_name = "atlantis" + +repo_owner = "cloudposse" + +branch = "master" + +alb_target_group_alarms_enabled = true + +ecs_alarms_enabled = true + +parent_zone_id = "Z3SO0TKDDQ0RGG" + +short_name = "ecs-atlantis-test" + +default_backend_image = "cloudposse/default-backend:0.1.2" + +chamber_service = "ecs-atlantis-test" diff --git a/examples/complete/main.tf b/examples/complete/main.tf new file mode 100644 index 0000000..50cdc4a --- /dev/null +++ b/examples/complete/main.tf @@ -0,0 +1,192 @@ +provider "aws" { + region = var.region +} + +module "label" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags +} + +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = var.vpc_cidr_block + tags = var.tags +} + +module "subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags +} + +module "alb" { + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + alb_access_logs_s3_bucket_force_destroy = true + access_logs_enabled = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags +} + +resource "aws_ecs_cluster" "default" { + name = module.label.id + tags = module.label.tags +} + +resource "aws_sns_topic" "sns_topic" { + name = module.label.id + display_name = "Test terraform-aws-ecs-atlantis" + tags = module.label.tags +} + +module "kms_key" { + source = "git::https://github.com/cloudposse/terraform-aws-kms-key.git?ref=tags/0.3.0" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + description = "Test terraform-aws-ecs-atlantis KMS key" + deletion_window_in_days = 7 + enable_key_rotation = false +} + +module "atlantis" { + source = "../.." + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + tags = var.tags + + region = var.region + vpc_id = module.vpc.vpc_id + policy_arn = var.policy_arn + ssh_private_key_name = var.ssh_private_key_name + ssh_public_key_name = var.ssh_public_key_name + kms_key_id = module.kms_key.key_id + chamber_service = var.chamber_service + + atlantis_gh_user = var.atlantis_gh_user + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_webhook_secret = var.atlantis_gh_webhook_secret + atlantis_log_level = var.atlantis_log_level + atlantis_repo_config = var.atlantis_repo_config + atlantis_repo_whitelist = var.atlantis_repo_whitelist + atlantis_port = var.atlantis_port + atlantis_webhook_format = var.atlantis_webhook_format + atlantis_url_format = var.atlantis_url_format + + default_backend_image = var.default_backend_image + healthcheck_path = var.healthcheck_path + short_name = var.short_name + hostname = var.hostname + parent_zone_id = var.parent_zone_id + + // Container + container_cpu = var.container_cpu + container_memory = var.container_memory + + // Authentication + authentication_type = var.authentication_type + alb_ingress_listener_unauthenticated_priority = var.alb_ingress_listener_unauthenticated_priority + alb_ingress_listener_authenticated_priority = var.alb_ingress_listener_authenticated_priority + alb_ingress_unauthenticated_hosts = var.alb_ingress_unauthenticated_hosts + alb_ingress_authenticated_hosts = var.alb_ingress_authenticated_hosts + alb_ingress_unauthenticated_paths = var.alb_ingress_unauthenticated_paths + alb_ingress_authenticated_paths = var.alb_ingress_authenticated_paths + authentication_cognito_user_pool_arn = var.authentication_cognito_user_pool_arn + authentication_cognito_user_pool_client_id = var.authentication_cognito_user_pool_client_id + authentication_cognito_user_pool_domain = var.authentication_cognito_user_pool_domain + authentication_oidc_client_id = var.authentication_oidc_client_id + authentication_oidc_client_secret = var.authentication_oidc_client_secret + authentication_oidc_issuer = var.authentication_oidc_issuer + authentication_oidc_authorization_endpoint = var.authentication_oidc_authorization_endpoint + authentication_oidc_token_endpoint = var.authentication_oidc_token_endpoint + authentication_oidc_user_info_endpoint = var.authentication_oidc_user_info_endpoint + + // ECS + private_subnet_ids = module.subnets.private_subnet_ids + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + security_group_ids = var.security_group_ids + desired_count = var.desired_count + launch_type = var.launch_type + + // ALB + alb_zone_id = module.alb.alb_zone_id + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_security_group = module.alb.security_group_id + alb_ingress_unauthenticated_listener_arns = [module.alb.http_listener_arn] + alb_ingress_unauthenticated_listener_arns_count = 1 + + // CodePipeline + codepipeline_enabled = var.codepipeline_enabled + github_oauth_token = var.github_oauth_token + github_webhooks_token = var.github_webhooks_token + repo_owner = var.repo_owner + repo_name = var.repo_name + branch = var.branch + build_timeout = var.build_timeout + webhook_enabled = var.webhook_enabled + webhook_secret_length = var.webhook_secret_length + webhook_events = var.webhook_events + codepipeline_s3_bucket_force_destroy = var.codepipeline_s3_bucket_force_destroy + + // Autoscaling + autoscaling_enabled = var.autoscaling_enabled + autoscaling_min_capacity = var.autoscaling_min_capacity + autoscaling_max_capacity = var.autoscaling_max_capacity + + // Alarms + alb_target_group_alarms_enabled = var.alb_target_group_alarms_enabled + ecs_alarms_enabled = var.ecs_alarms_enabled + alb_target_group_alarms_alarm_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_ok_actions = [aws_sns_topic.sns_topic.arn] + alb_target_group_alarms_insufficient_data_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_cpu_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_high_ok_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_alarm_actions = [aws_sns_topic.sns_topic.arn] + ecs_alarms_memory_utilization_low_ok_actions = [aws_sns_topic.sns_topic.arn] +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf new file mode 100644 index 0000000..5a2f403 --- /dev/null +++ b/examples/complete/outputs.tf @@ -0,0 +1,335 @@ +output "public_subnet_cidrs" { + value = module.subnets.public_subnet_cidrs + description = "Public subnet CIDRs" +} + +output "private_subnet_cidrs" { + value = module.subnets.private_subnet_cidrs + description = "Private subnet CIDRs" +} + +output "vpc_cidr" { + value = module.vpc.vpc_cidr_block + description = "VPC ID" +} + +output "atlantis_ssh_public_key" { + description = "Atlantis SSH Public Key" + value = module.atlantis.atlantis_ssh_public_key +} + +output "atlantis_url" { + description = "The URL endpoint for the atlantis server" + value = module.atlantis.atlantis_url +} + +output "atlantis_webhook_url" { + description = "atlantis webhook URL" + value = module.atlantis.atlantis_webhook_url +} + +output "alb_name" { + description = "The ARN suffix of the ALB" + value = module.alb.alb_name +} + +output "alb_arn" { + description = "The ARN of the ALB" + value = module.alb.alb_arn +} + +output "alb_arn_suffix" { + description = "The ARN suffix of the ALB" + value = module.alb.alb_arn_suffix +} + +output "alb_dns_name" { + description = "DNS name of ALB" + value = module.alb.alb_dns_name +} + +output "alb_zone_id" { + description = "The ID of the zone which ALB is provisioned" + value = module.alb.alb_zone_id +} + +output "alb_security_group_id" { + description = "The security group ID of the ALB" + value = module.alb.security_group_id +} + +output "alb_default_target_group_arn" { + description = "The default target group ARN" + value = module.alb.default_target_group_arn +} + +output "alb_http_listener_arn" { + description = "The ARN of the HTTP listener" + value = module.alb.http_listener_arn +} + +output "alb_listener_arns" { + description = "A list of all the listener ARNs" + value = module.alb.listener_arns +} + +output "alb_access_logs_bucket_id" { + description = "The S3 bucket ID for access logs" + value = module.alb.access_logs_bucket_id +} + +output "ecr_registry_id" { + value = module.atlantis.ecr_registry_id + description = "Registry ID" +} + +output "ecr_registry_url" { + value = module.atlantis.ecr_registry_url + description = "Registry URL" +} + +output "ecr_repository_name" { + value = module.atlantis.ecr_repository_name + description = "Registry name" +} + +output "alb_ingress_target_group_name" { + description = "ALB Target Group name" + value = module.atlantis.alb_ingress_target_group_name +} + +output "alb_ingress_target_group_arn" { + description = "ALB Target Group ARN" + value = module.atlantis.alb_ingress_target_group_arn +} + +output "alb_ingress_target_group_arn_suffix" { + description = "ALB Target Group ARN suffix" + value = module.atlantis.alb_ingress_target_group_arn_suffix +} + +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.atlantis.container_definition_json +} + +output "container_definition_json_map" { + description = "JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition" + value = module.atlantis.container_definition_json_map +} + +output "ecs_exec_role_policy_id" { + description = "The ECS service role policy ID, in the form of `role_name:role_policy_name`" + value = module.atlantis.ecs_exec_role_policy_id +} + +output "ecs_exec_role_policy_name" { + description = "ECS service role name" + value = module.atlantis.ecs_exec_role_policy_name +} + +output "ecs_service_name" { + description = "ECS Service name" + value = module.atlantis.ecs_service_name +} + +output "ecs_service_role_arn" { + description = "ECS Service role ARN" + value = module.atlantis.ecs_service_role_arn +} + +output "ecs_task_exec_role_name" { + description = "ECS Task role name" + value = module.atlantis.ecs_task_exec_role_name +} + +output "ecs_task_exec_role_arn" { + description = "ECS Task exec role ARN" + value = module.atlantis.ecs_task_exec_role_arn +} + +output "ecs_task_role_name" { + description = "ECS Task role name" + value = module.atlantis.ecs_task_role_name +} + +output "ecs_task_role_arn" { + description = "ECS Task role ARN" + value = module.atlantis.ecs_task_role_arn +} + +output "ecs_task_role_id" { + description = "ECS Task role id" + value = module.atlantis.ecs_task_role_id +} + +output "ecs_service_security_group_id" { + description = "Security Group ID of the ECS task" + value = module.atlantis.ecs_service_security_group_id +} + +output "ecs_task_definition_family" { + description = "ECS task definition family" + value = module.atlantis.ecs_task_definition_family +} + +output "ecs_task_definition_revision" { + description = "ECS task definition revision" + value = module.atlantis.ecs_task_definition_revision +} + +output "codebuild_project_name" { + description = "CodeBuild project name" + value = module.atlantis.codebuild_project_name +} + +output "codebuild_project_id" { + description = "CodeBuild project ID" + value = module.atlantis.codebuild_project_id +} + +output "codebuild_role_id" { + description = "CodeBuild IAM Role ID" + value = module.atlantis.codebuild_role_id +} + +output "codebuild_role_arn" { + description = "CodeBuild IAM Role ARN" + value = module.atlantis.codebuild_role_arn +} + +output "codebuild_cache_bucket_name" { + description = "CodeBuild cache S3 bucket name" + value = module.atlantis.codebuild_cache_bucket_name +} + +output "codebuild_cache_bucket_arn" { + description = "CodeBuild cache S3 bucket ARN" + value = module.atlantis.codebuild_cache_bucket_arn +} + +output "codebuild_badge_url" { + description = "The URL of the build badge when badge_enabled is enabled" + value = module.atlantis.codebuild_badge_url +} + +output "codepipeline_id" { + description = "CodePipeline ID" + value = module.atlantis.codepipeline_id +} + +output "codepipeline_arn" { + description = "CodePipeline ARN" + value = module.atlantis.codepipeline_arn +} + +output "codepipeline_webhook_id" { + description = "The CodePipeline webhook's ID" + value = module.atlantis.codepipeline_webhook_id +} + +output "codepipeline_webhook_url" { + description = "The CodePipeline webhook's URL. POST events to this endpoint to trigger the target" + value = module.atlantis.codepipeline_webhook_url + sensitive = true +} + +output "ecs_cloudwatch_autoscaling_scale_up_policy_arn" { + description = "ARN of the scale up policy" + value = module.atlantis.ecs_cloudwatch_autoscaling_scale_up_policy_arn +} + +output "ecs_cloudwatch_autoscaling_scale_down_policy_arn" { + description = "ARN of the scale down policy" + value = module.atlantis.ecs_cloudwatch_autoscaling_scale_down_policy_arn +} + +output "ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id" { + value = module.atlantis.ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id + description = "ECS CPU utilization high CloudWatch metric alarm ID" +} + +output "ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn" { + value = module.atlantis.ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn + description = "ECS CPU utilization high CloudWatch metric alarm ARN" +} + +output "ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id" { + value = module.atlantis.ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id + description = "ECS CPU utilization low CloudWatch metric alarm ID" +} + +output "ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn" { + value = module.atlantis.ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn + description = "ECS CPU utilization low CloudWatch metric alarm ARN" +} + +output "ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id" { + value = module.atlantis.ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id + description = "ECS Memory utilization high CloudWatch metric alarm ID" +} + +output "ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn" { + value = module.atlantis.ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn + description = "ECS Memory utilization high CloudWatch metric alarm ARN" +} + +output "ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id" { + value = module.atlantis.ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id + description = "ECS Memory utilization low CloudWatch metric alarm ID" +} + +output "ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn" { + value = module.atlantis.ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn + description = "ECS Memory utilization low CloudWatch metric alarm ARN" +} + +output "httpcode_target_3xx_count_cloudwatch_metric_alarm_id" { + value = module.atlantis.httpcode_target_3xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 3xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_3xx_count_cloudwatch_metric_alarm_arn" { + value = module.atlantis.httpcode_target_3xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 3xx count CloudWatch metric alarm ARN" +} + +output "httpcode_target_4xx_count_cloudwatch_metric_alarm_id" { + value = module.atlantis.httpcode_target_4xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 4xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_4xx_count_cloudwatch_metric_alarm_arn" { + value = module.atlantis.httpcode_target_4xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 4xx count CloudWatch metric alarm ARN" +} + +output "httpcode_target_5xx_count_cloudwatch_metric_alarm_id" { + value = module.atlantis.httpcode_target_5xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 5xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_5xx_count_cloudwatch_metric_alarm_arn" { + value = module.atlantis.httpcode_target_5xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 5xx count CloudWatch metric alarm ARN" +} + +output "httpcode_elb_5xx_count_cloudwatch_metric_alarm_id" { + value = module.atlantis.httpcode_elb_5xx_count_cloudwatch_metric_alarm_id + description = "ALB 5xx count CloudWatch metric alarm ID" +} + +output "httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn" { + value = module.atlantis.httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn + description = "ALB 5xx count CloudWatch metric alarm ARN" +} + +output "target_response_time_average_cloudwatch_metric_alarm_id" { + value = module.atlantis.target_response_time_average_cloudwatch_metric_alarm_id + description = "ALB Target Group response time average CloudWatch metric alarm ID" +} + +output "target_response_time_average_cloudwatch_metric_alarm_arn" { + value = module.atlantis.target_response_time_average_cloudwatch_metric_alarm_arn + description = "ALB Target Group response time average CloudWatch metric alarm ARN" +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf new file mode 100644 index 0000000..a4d4a7e --- /dev/null +++ b/examples/complete/variables.tf @@ -0,0 +1,387 @@ +variable "region" { + type = string + description = "AWS Region for S3 bucket" +} + +variable "availability_zones" { + type = list(string) + description = "List of availability zones" +} + +variable "vpc_cidr_block" { + type = string + description = "VPC CIDR block" +} + +variable "namespace" { + type = string + description = "Namespace (e.g. `eg` or `cp`)" + default = "" +} + +variable "stage" { + type = string + description = "Stage (e.g. `prod`, `dev`, `staging`)" + default = "" +} + +variable "name" { + type = string + description = "Name of the application" +} + +variable "delimiter" { + type = string + default = "-" + description = "Delimiter between `namespace`, `stage`, `name` and `attributes`" +} + +variable "attributes" { + type = list(string) + description = "Additional attributes (_e.g._ \"1\")" + default = [] +} + +variable "tags" { + type = map(string) + description = "Additional tags (_e.g._ { BusinessUnit : ABC })" + default = {} +} + +variable "launch_type" { + type = string + description = "The ECS launch type (valid options: FARGATE or EC2)" + default = "FARGATE" +} + +variable "default_backend_image" { + type = string + default = "cloudposse/default-backend:0.1.2" + description = "ECS default (bootstrap) image" +} + +variable "github_oauth_token" { + type = string + description = "GitHub OAuth token. If not provided the token is looked up from SSM" +} + +variable "github_webhooks_token" { + type = string + description = "GitHub OAuth Token with permissions to create webhooks. If not provided the token is looked up from SSM" +} + +variable "codepipeline_enabled" { + type = bool + description = "A boolean to enable/disable AWS Codepipeline and ECR" + default = true +} + +variable "codepipeline_s3_bucket_force_destroy" { + type = bool + description = "A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error" + default = false +} + +variable "enabled" { + type = bool + default = true + description = "Whether to create the resources. Set to `false` to prevent the module from creating any resources" +} + +variable "chamber_service" { + type = string + default = "atlantis" + description = "SSM parameter service name for use with chamber. This is used in chamber_format where /$chamber_service/$parameter would be the default." +} + +variable "autoscaling_enabled" { + type = bool + description = "A boolean to enable/disable Autoscaling policy for ECS Service" + default = true +} + +variable "build_timeout" { + type = number + default = 20 + description = "How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed." +} + +variable "branch" { + type = string + default = "master" + description = "Atlantis branch of the GitHub repository, _e.g._ `master`" +} + +variable "repo_name" { + type = string + description = "GitHub repository name of the atlantis to be built and deployed to ECS." +} + +variable "repo_owner" { + type = string + description = "GitHub organization containing the Atlantis repository" +} + +variable "atlantis_repo_config" { + type = string + description = "Path to atlantis server-side repo config file (https://www.runatlantis.io/docs/server-side-repo-config.html)" + default = "atlantis-repo-config.yaml" +} + +variable "atlantis_repo_whitelist" { + type = list(string) + description = "Whitelist of repositories Atlantis will accept webhooks from" + default = [] +} + +variable "healthcheck_path" { + type = string + description = "Healthcheck path" + default = "/healthz" +} + +variable "desired_count" { + type = number + description = "Atlantis desired number of tasks" + default = 1 +} + +variable "short_name" { + type = string + description = "Alantis short DNS name (e.g. `atlantis`)" + default = "atlantis" +} + +variable "hostname" { + type = string + description = "Atlantis URL" + default = "" +} + +variable "atlantis_gh_user" { + type = string + description = "Atlantis GitHub user" +} + +variable "atlantis_gh_team_whitelist" { + type = string + description = "Atlantis GitHub team whitelist" + default = "" +} + +variable "atlantis_gh_webhook_secret" { + type = string + description = "Atlantis GitHub webhook secret" + default = "" +} + +variable "atlantis_log_level" { + type = string + description = "Atlantis log level" + default = "info" +} + +variable "atlantis_port" { + type = number + description = "Atlantis container port" + default = 4141 +} + +variable "atlantis_webhook_format" { + type = string + default = "https://%s/events" + description = "Template for the Atlantis webhook URL which is populated with the hostname" +} + +variable "atlantis_url_format" { + type = string + default = "https://%s" + description = "Template for the Atlantis URL which is populated with the hostname" +} + +variable "autoscaling_min_capacity" { + type = number + description = "Atlantis minimum tasks to run" + default = 1 +} + +variable "autoscaling_max_capacity" { + type = number + description = "Atlantis maximum tasks to run" + default = 1 +} + +variable "container_cpu" { + type = number + description = "Atlantis CPUs per task" + default = 256 +} + +variable "container_memory" { + type = number + description = "Atlantis memory per task" + default = 512 +} + +variable "policy_arn" { + type = string + default = "arn:aws:iam::aws:policy/AdministratorAccess" + description = "Permission to grant to atlantis server" +} + +variable "webhook_enabled" { + type = bool + description = "Set to false to prevent the module from creating any webhook resources" + default = false +} + +variable "webhook_secret_length" { + type = number + default = 32 + description = "GitHub webhook secret length" +} + +variable "webhook_events" { + type = list(string) + description = "A list of events which should trigger the webhook." + + default = [ + "issue_comment", + "pull_request", + "pull_request_review", + "pull_request_review_comment", + "push", + ] +} + +variable "ssh_private_key_name" { + type = string + default = "atlantis_ssh_private_key" + description = "Atlantis SSH private key name" +} + +variable "ssh_public_key_name" { + type = string + default = "atlantis_ssh_public_key" + description = "Atlantis SSH public key name" +} + +variable "security_group_ids" { + type = list(string) + default = [] + description = "Additional Security Group IDs to allow into ECS Service." +} + +variable "parent_zone_id" { + type = string + description = "The zone ID where the DNS record for the `short_name` will be written" + default = "" +} + +variable "alb_ingress_listener_unauthenticated_priority" { + type = number + default = 50 + description = "The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority" +} + +variable "alb_ingress_listener_authenticated_priority" { + type = number + default = 100 + description = "The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority" +} + +variable "alb_ingress_unauthenticated_hosts" { + type = list(string) + default = [] + description = "Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined)" +} + +variable "alb_ingress_authenticated_hosts" { + type = list(string) + default = [] + description = "Authenticated hosts to match in Hosts header (a maximum of 1 can be defined)" +} + +variable "alb_ingress_unauthenticated_paths" { + type = list(string) + default = ["/events"] + description = "Unauthenticated path pattern to match (a maximum of 1 can be defined)" +} + +variable "alb_ingress_authenticated_paths" { + type = list(string) + default = ["/*"] + description = "Authenticated path pattern to match (a maximum of 1 can be defined)" +} + +variable "authentication_type" { + type = string + default = "" + description = "Authentication type. Supported values are `COGNITO` and `OIDC`" +} + +variable "authentication_cognito_user_pool_arn" { + type = string + description = "Cognito User Pool ARN" + default = "" +} + +variable "authentication_cognito_user_pool_client_id" { + type = string + description = "Cognito User Pool Client ID" + default = "" +} + +variable "authentication_cognito_user_pool_domain" { + type = string + description = "Cognito User Pool Domain. The User Pool Domain should be set to the domain prefix (`xxx`) instead of full domain (https://xxx.auth.us-west-2.amazoncognito.com)" + default = "" +} + +variable "authentication_oidc_client_id" { + type = string + description = "OIDC Client ID" + default = "" +} + +variable "authentication_oidc_client_secret" { + type = string + description = "OIDC Client Secret" + default = "" +} + +variable "authentication_oidc_issuer" { + type = string + description = "OIDC Issuer" + default = "" +} + +variable "authentication_oidc_authorization_endpoint" { + type = string + description = "OIDC Authorization Endpoint" + default = "" +} + +variable "authentication_oidc_token_endpoint" { + type = string + description = "OIDC Token Endpoint" + default = "" +} + +variable "authentication_oidc_user_info_endpoint" { + type = string + description = "OIDC User Info Endpoint" + default = "" +} + +variable "alb_target_group_alarms_enabled" { + type = bool + description = "A boolean to enable/disable CloudWatch Alarms for ALB Target metrics" + default = true +} + +variable "ecs_alarms_enabled" { + type = bool + description = "A boolean to enable/disable CloudWatch Alarms for ECS Service metrics" + default = false +} diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf new file mode 100644 index 0000000..9840ed7 --- /dev/null +++ b/examples/complete/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + template = "~> 2.0" + null = "~> 2.0" + local = "~> 1.3" + } +} diff --git a/examples/with_cognito_authentication/main.tf b/examples/with_cognito_authentication/main.tf index bb02f5f..034006a 100644 --- a/examples/with_cognito_authentication/main.tf +++ b/examples/with_cognito_authentication/main.tf @@ -1,113 +1,124 @@ provider "aws" { - region = "${var.region}" + region = var.region } -module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - cidr_block = "172.16.0.0/16" +data "aws_availability_zones" "available" { } -data "aws_availability_zones" "available" {} - locals { - availability_zones = "${slice(data.aws_availability_zones.available.names, 0, 2)}" + availability_zones = slice(data.aws_availability_zones.available.names, 0, 2) +} + +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = "172.16.0.0/16" + tags = var.tags } module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.8.0" - availability_zones = "${local.availability_zones}" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - region = "${var.region}" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = local.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags } module "alb" { - source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.2.6" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - attributes = ["${compact(concat(var.attributes, list("alb")))}"] - vpc_id = "${module.vpc.vpc_id}" - ip_address_type = "ipv4" - subnet_ids = ["${module.subnets.public_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - access_logs_region = "${var.region}" - https_enabled = "true" - http_ingress_cidr_blocks = ["0.0.0.0/0"] - https_ingress_cidr_blocks = ["0.0.0.0/0"] - certificate_arn = "${var.certificate_arn}" - health_check_interval = "60" + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + alb_access_logs_s3_bucket_force_destroy = true + access_logs_enabled = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags } module "ecs_cluster_label" { - source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.2.1" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - tags = "${var.tags}" - attributes = "${var.attributes}" - delimiter = "${var.delimiter}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + name = var.name + namespace = var.namespace + stage = var.stage + tags = var.tags + attributes = var.attributes + delimiter = var.delimiter } # ECS Cluster (needed even if using FARGATE launch type) resource "aws_ecs_cluster" "default" { - name = "${module.ecs_cluster_label.id}" + name = module.ecs_cluster_label.id } module "atlantis" { source = "../.." - enabled = "true" - name = "${var.name}" - namespace = "${var.namespace}" - region = "${var.region}" - stage = "${var.stage}" - - atlantis_gh_team_whitelist = "${var.atlantis_gh_team_whitelist}" - atlantis_gh_user = "${var.atlantis_gh_user}" - atlantis_repo_whitelist = ["${var.atlantis_repo_whitelist}"] - - alb_arn_suffix = "${module.alb.alb_arn_suffix}" - alb_dns_name = "${module.alb.alb_dns_name}" - alb_name = "${module.alb.alb_name}" - alb_zone_id = "${module.alb.alb_zone_id}" - - container_cpu = "${var.atlantis_container_cpu}" - container_memory = "${var.atlantis_container_memory}" - - branch = "${var.atlantis_branch}" - parent_zone_id = "${var.parent_zone_id}" - ecs_cluster_arn = "${aws_ecs_cluster.default.arn}" - ecs_cluster_name = "${aws_ecs_cluster.default.name}" - repo_name = "${var.atlantis_repo_name}" - repo_owner = "${var.atlantis_repo_owner}" - private_subnet_ids = ["${module.subnets.private_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - vpc_id = "${module.vpc.vpc_id}" - - alb_ingress_authenticated_listener_arns = ["${module.alb.https_listener_arn}"] + enabled = true + name = var.name + namespace = var.namespace + region = var.region + stage = var.stage + + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_user = var.atlantis_gh_user + atlantis_repo_whitelist = [var.atlantis_repo_whitelist] + + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_name = module.alb.alb_name + alb_zone_id = module.alb.alb_zone_id + alb_security_group = module.alb.security_group_id + + container_cpu = var.atlantis_container_cpu + container_memory = var.atlantis_container_memory + + branch = var.atlantis_branch + parent_zone_id = var.parent_zone_id + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + repo_name = var.atlantis_repo_name + repo_owner = var.atlantis_repo_owner + private_subnet_ids = [module.subnets.private_subnet_ids] + security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_id = module.vpc.vpc_id + + alb_ingress_authenticated_listener_arns = [module.alb.https_listener_arn] alb_ingress_authenticated_listener_arns_count = 1 - alb_ingress_unauthenticated_listener_arns = ["${module.alb.listener_arns}"] + alb_ingress_unauthenticated_listener_arns = [module.alb.listener_arns] alb_ingress_unauthenticated_listener_arns_count = 2 # Unauthenticated paths (with higher priority than the authenticated paths) alb_ingress_unauthenticated_paths = ["/events"] - alb_ingress_listener_unauthenticated_priority = "50" + alb_ingress_listener_unauthenticated_priority = 50 # Authenticated paths alb_ingress_authenticated_paths = ["/*"] - alb_ingress_listener_authenticated_priority = "100" + alb_ingress_listener_authenticated_priority = 100 authentication_type = "COGNITO" - authentication_cognito_user_pool_arn = "${var.cognito_user_pool_arn}" - authentication_cognito_user_pool_client_id = "${var.cognito_user_pool_client_id}" - authentication_cognito_user_pool_domain = "${var.cognito_user_pool_domain}" + authentication_cognito_user_pool_arn = var.cognito_user_pool_arn + authentication_cognito_user_pool_client_id = var.cognito_user_pool_client_id + authentication_cognito_user_pool_domain = var.cognito_user_pool_domain } diff --git a/examples/with_cognito_authentication/outputs.tf b/examples/with_cognito_authentication/outputs.tf index dfe3108..12ec479 100644 --- a/examples/with_cognito_authentication/outputs.tf +++ b/examples/with_cognito_authentication/outputs.tf @@ -1,3 +1,3 @@ output "atlantis_url" { - value = "${module.atlantis.atlantis_url}" + value = module.atlantis.atlantis_url } diff --git a/examples/with_cognito_authentication/variables.tf b/examples/with_cognito_authentication/variables.tf index e3905e0..291200c 100644 --- a/examples/with_cognito_authentication/variables.tf +++ b/examples/with_cognito_authentication/variables.tf @@ -1,114 +1,114 @@ variable "namespace" { - type = "string" + type = string description = "Namespace (e.g. `cp` or `cloudposse`)" default = "eg" } variable "stage" { - type = "string" + type = string description = "Stage (e.g. `prod`, `dev`, `staging`)" default = "testing" } variable "name" { - type = "string" + type = string description = "Application or solution name (e.g. `app`)" default = "atlantis" } variable "delimiter" { - type = "string" + type = string default = "-" description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" } variable "attributes" { - type = "list" + type = list(string) default = [] description = "Additional attributes (e.g. `1`)" } variable "tags" { - type = "map" + type = map(string) default = {} description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)" } variable "region" { - type = "string" + type = string description = "AWS Region" - default = "us-west-2" + default = "us-east-2" } variable "certificate_arn" { - type = "string" + type = string description = "SSL certificate ARN for ALB HTTPS endpoints" } variable "cognito_user_pool_arn" { - type = "string" + type = string description = "Cognito User Pool ARN" } variable "cognito_user_pool_client_id" { - type = "string" + type = string description = "Cognito User Pool Client ID" } variable "cognito_user_pool_domain" { - type = "string" + type = string description = "Cognito User Pool Domain. The User Pool Domain should be set to the domain prefix (`xxx`) instead of full domain (https://xxx.auth.us-west-2.amazoncognito.com)" } variable "atlantis_gh_team_whitelist" { - type = "string" + type = string description = "Atlantis GitHub team whitelist" default = "engineering:plan,devops:*" } variable "atlantis_gh_user" { - type = "string" + type = string description = "Atlantis GitHub user" default = "examplebot" } variable "atlantis_repo_whitelist" { - type = "list" + type = list(string) description = "Whitelist of repositories Atlantis will accept webhooks from" default = ["github.com/example/*"] } variable "atlantis_repo_name" { - type = "string" + type = string description = "GitHub repository name of the atlantis to be built and deployed to ECS" default = "atlantis" } variable "atlantis_repo_owner" { - type = "string" + type = string description = "GitHub organization containing the Atlantis repository" default = "cloudposse" } variable "atlantis_branch" { - type = "string" + type = string description = "Atlantis branch of the GitHub repository, _e.g._ `master`" default = "master" } variable "atlantis_container_cpu" { - type = "string" + type = number description = "The vCPU setting to control cpu limits of container. (If FARGATE launch type is used below, this must be a supported vCPU size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "256" + default = 256 } variable "atlantis_container_memory" { - type = "string" + type = number description = "The amount of RAM to allow container to use in MB. (If FARGATE launch type is used below, this must be a supported Memory size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "512" + default = 512 } variable "parent_zone_id" { - type = "string" + type = string description = "The zone ID where the DNS record for the atlantis `short_name` will be written" } diff --git a/examples/with_cognito_authentication/versions.tf b/examples/with_cognito_authentication/versions.tf new file mode 100644 index 0000000..9840ed7 --- /dev/null +++ b/examples/with_cognito_authentication/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + template = "~> 2.0" + null = "~> 2.0" + local = "~> 1.3" + } +} diff --git a/examples/with_google_oidc_authentication/main.tf b/examples/with_google_oidc_authentication/main.tf index 2ef5270..0a861b6 100644 --- a/examples/with_google_oidc_authentication/main.tf +++ b/examples/with_google_oidc_authentication/main.tf @@ -1,114 +1,124 @@ provider "aws" { - region = "${var.region}" -} - -module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - cidr_block = "172.16.0.0/16" + region = var.region } data "aws_availability_zones" "available" {} locals { - availability_zones = "${slice(data.aws_availability_zones.available.names, 0, 2)}" + availability_zones = slice(data.aws_availability_zones.available.names, 0, 2) +} + +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = "172.16.0.0/16" + tags = var.tags } module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.8.0" - availability_zones = "${local.availability_zones}" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - region = "${var.region}" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = local.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags } module "alb" { - source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.2.6" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - attributes = ["${compact(concat(var.attributes, list("alb")))}"] - vpc_id = "${module.vpc.vpc_id}" - ip_address_type = "ipv4" - subnet_ids = ["${module.subnets.public_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - access_logs_region = "${var.region}" - https_enabled = "true" - http_ingress_cidr_blocks = ["0.0.0.0/0"] - https_ingress_cidr_blocks = ["0.0.0.0/0"] - certificate_arn = "${var.certificate_arn}" - health_check_interval = "60" + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + alb_access_logs_s3_bucket_force_destroy = true + access_logs_enabled = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags } module "ecs_cluster_label" { - source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.2.1" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - tags = "${var.tags}" - attributes = "${var.attributes}" - delimiter = "${var.delimiter}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + name = var.name + namespace = var.namespace + stage = var.stage + tags = var.tags + attributes = var.attributes + delimiter = var.delimiter } # ECS Cluster (needed even if using FARGATE launch type) resource "aws_ecs_cluster" "default" { - name = "${module.ecs_cluster_label.id}" + name = module.ecs_cluster_label.id } module "atlantis" { source = "../.." - enabled = "true" - name = "${var.name}" - namespace = "${var.namespace}" - region = "${var.region}" - stage = "${var.stage}" - - atlantis_gh_team_whitelist = "${var.atlantis_gh_team_whitelist}" - atlantis_gh_user = "${var.atlantis_gh_user}" - atlantis_repo_whitelist = ["${var.atlantis_repo_whitelist}"] - - alb_arn_suffix = "${module.alb.alb_arn_suffix}" - alb_dns_name = "${module.alb.alb_dns_name}" - alb_name = "${module.alb.alb_name}" - alb_zone_id = "${module.alb.alb_zone_id}" - - container_cpu = "${var.atlantis_container_cpu}" - container_memory = "${var.atlantis_container_memory}" - - branch = "${var.atlantis_branch}" - parent_zone_id = "${var.parent_zone_id}" - ecs_cluster_arn = "${aws_ecs_cluster.default.arn}" - ecs_cluster_name = "${aws_ecs_cluster.default.name}" - repo_name = "${var.atlantis_repo_name}" - repo_owner = "${var.atlantis_repo_owner}" - private_subnet_ids = ["${module.subnets.private_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - vpc_id = "${module.vpc.vpc_id}" - - alb_ingress_authenticated_listener_arns = ["${module.alb.https_listener_arn}"] + enabled = true + name = var.name + namespace = var.namespace + region = var.region + stage = var.stage + + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_user = var.atlantis_gh_user + atlantis_repo_whitelist = var.atlantis_repo_whitelist + + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_name = module.alb.alb_name + alb_zone_id = module.alb.alb_zone_id + alb_security_group = module.alb.security_group_id + + container_cpu = var.atlantis_container_cpu + container_memory = var.atlantis_container_memory + + branch = var.atlantis_branch + parent_zone_id = var.parent_zone_id + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + repo_name = var.atlantis_repo_name + repo_owner = var.atlantis_repo_owner + private_subnet_ids = module.subnets.private_subnet_ids + security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_id = module.vpc.vpc_id + + alb_ingress_authenticated_listener_arns = [module.alb.https_listener_arn] alb_ingress_authenticated_listener_arns_count = 1 - alb_ingress_unauthenticated_listener_arns = ["${module.alb.listener_arns}"] + alb_ingress_unauthenticated_listener_arns = module.alb.listener_arns alb_ingress_unauthenticated_listener_arns_count = 2 # Unauthenticated paths (with higher priority than the authenticated paths) alb_ingress_unauthenticated_paths = ["/events"] - alb_ingress_listener_unauthenticated_priority = "50" + alb_ingress_listener_unauthenticated_priority = 50 # Authenticated paths alb_ingress_authenticated_paths = ["/*"] - alb_ingress_listener_authenticated_priority = "100" + alb_ingress_listener_authenticated_priority = 100 authentication_type = "OIDC" - authentication_oidc_client_id = "${var.google_oidc_client_id}" - authentication_oidc_client_secret = "${var.google_oidc_client_secret}" + authentication_oidc_client_id = var.google_oidc_client_id + authentication_oidc_client_secret = var.google_oidc_client_secret authentication_oidc_issuer = "https://accounts.google.com" authentication_oidc_authorization_endpoint = "https://accounts.google.com/o/oauth2/v2/auth" authentication_oidc_token_endpoint = "https://oauth2.googleapis.com/token" diff --git a/examples/with_google_oidc_authentication/outputs.tf b/examples/with_google_oidc_authentication/outputs.tf index dfe3108..12ec479 100644 --- a/examples/with_google_oidc_authentication/outputs.tf +++ b/examples/with_google_oidc_authentication/outputs.tf @@ -1,3 +1,3 @@ output "atlantis_url" { - value = "${module.atlantis.atlantis_url}" + value = module.atlantis.atlantis_url } diff --git a/examples/with_google_oidc_authentication/variables.tf b/examples/with_google_oidc_authentication/variables.tf index 31fcc66..fe96ec7 100644 --- a/examples/with_google_oidc_authentication/variables.tf +++ b/examples/with_google_oidc_authentication/variables.tf @@ -1,109 +1,109 @@ variable "namespace" { - type = "string" + type = string description = "Namespace (e.g. `cp` or `cloudposse`)" default = "eg" } variable "stage" { - type = "string" + type = string description = "Stage (e.g. `prod`, `dev`, `staging`)" default = "testing" } variable "name" { - type = "string" + type = string description = "Application or solution name (e.g. `app`)" default = "atlantis" } variable "delimiter" { - type = "string" + type = string default = "-" description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" } variable "attributes" { - type = "list" + type = list(string) default = [] description = "Additional attributes (e.g. `1`)" } variable "tags" { - type = "map" + type = map(string) default = {} description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)" } variable "region" { - type = "string" + type = string description = "AWS Region" - default = "us-west-2" + default = "us-east-2" } variable "certificate_arn" { - type = "string" + type = string description = "SSL certificate ARN for ALB HTTPS endpoints" } variable "google_oidc_client_id" { - type = "string" + type = string description = "Google OIDC Client ID. Use this URL to create a Google OAuth 2.0 Client and obtain the Client ID and Client Secret: https://console.developers.google.com/apis/credentials" } variable "google_oidc_client_secret" { - type = "string" + type = string description = "Google OIDC Client Secret. Use this URL to create a Google OAuth 2.0 Client and obtain the Client ID and Client Secret: https://console.developers.google.com/apis/credentials" } variable "atlantis_gh_team_whitelist" { - type = "string" + type = string description = "Atlantis GitHub team whitelist" default = "engineering:plan,devops:*" } variable "atlantis_gh_user" { - type = "string" + type = string description = "Atlantis GitHub user" default = "examplebot" } variable "atlantis_repo_whitelist" { - type = "list" + type = list(string) description = "Whitelist of repositories Atlantis will accept webhooks from" default = ["github.com/example/*"] } variable "atlantis_repo_name" { - type = "string" + type = string description = "GitHub repository name of the atlantis to be built and deployed to ECS" default = "atlantis" } variable "atlantis_repo_owner" { - type = "string" + type = string description = "GitHub organization containing the Atlantis repository" default = "cloudposse" } variable "atlantis_branch" { - type = "string" + type = string description = "Atlantis branch of the GitHub repository, _e.g._ `master`" default = "master" } variable "atlantis_container_cpu" { - type = "string" + type = number description = "The vCPU setting to control cpu limits of container. (If FARGATE launch type is used below, this must be a supported vCPU size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "256" + default = 256 } variable "atlantis_container_memory" { - type = "string" + type = number description = "The amount of RAM to allow container to use in MB. (If FARGATE launch type is used below, this must be a supported Memory size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "512" + default = 512 } variable "parent_zone_id" { - type = "string" + type = string description = "The zone ID where the DNS record for the atlantis `short_name` will be written" } diff --git a/examples/with_google_oidc_authentication/versions.tf b/examples/with_google_oidc_authentication/versions.tf new file mode 100644 index 0000000..9840ed7 --- /dev/null +++ b/examples/with_google_oidc_authentication/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + template = "~> 2.0" + null = "~> 2.0" + local = "~> 1.3" + } +} diff --git a/examples/without_authentication/main.tf b/examples/without_authentication/main.tf index 2fe8f4a..3ed7b71 100644 --- a/examples/without_authentication/main.tf +++ b/examples/without_authentication/main.tf @@ -1,103 +1,113 @@ provider "aws" { - region = "${var.region}" -} - -module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - cidr_block = "172.16.0.0/16" + region = var.region } data "aws_availability_zones" "available" {} locals { - availability_zones = "${slice(data.aws_availability_zones.available.names, 0, 2)}" + availability_zones = slice(data.aws_availability_zones.available.names, 0, 2) +} + +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + cidr_block = "172.16.0.0/16" + tags = var.tags } module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.8.0" - availability_zones = "${local.availability_zones}" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - region = "${var.region}" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.1" + availability_zones = local.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false + tags = var.tags } module "alb" { - source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.2.6" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - attributes = ["${compact(concat(var.attributes, list("alb")))}"] - vpc_id = "${module.vpc.vpc_id}" - ip_address_type = "ipv4" - subnet_ids = ["${module.subnets.public_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - access_logs_region = "${var.region}" - https_enabled = "true" - http_ingress_cidr_blocks = ["0.0.0.0/0"] - https_ingress_cidr_blocks = ["0.0.0.0/0"] - certificate_arn = "${var.certificate_arn}" - health_check_interval = "60" + source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.7.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + security_group_ids = [module.vpc.vpc_default_security_group_id] + subnet_ids = module.subnets.public_subnet_ids + internal = false + http_enabled = true + alb_access_logs_s3_bucket_force_destroy = true + access_logs_enabled = true + access_logs_region = var.region + cross_zone_load_balancing_enabled = true + http2_enabled = true + deletion_protection_enabled = false + tags = var.tags } module "ecs_cluster_label" { - source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.2.1" - name = "${var.name}" - namespace = "${var.namespace}" - stage = "${var.stage}" - tags = "${var.tags}" - attributes = "${var.attributes}" - delimiter = "${var.delimiter}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + name = var.name + namespace = var.namespace + stage = var.stage + tags = var.tags + attributes = var.attributes + delimiter = var.delimiter } # ECS Cluster (needed even if using FARGATE launch type) resource "aws_ecs_cluster" "default" { - name = "${module.ecs_cluster_label.id}" + name = module.ecs_cluster_label.id } module "atlantis" { source = "../.." - enabled = "true" - name = "${var.name}" - namespace = "${var.namespace}" - region = "${var.region}" - stage = "${var.stage}" + enabled = true + name = var.name + namespace = var.namespace + region = var.region + stage = var.stage - atlantis_gh_team_whitelist = "${var.atlantis_gh_team_whitelist}" - atlantis_gh_user = "${var.atlantis_gh_user}" - atlantis_repo_whitelist = ["${var.atlantis_repo_whitelist}"] + atlantis_gh_team_whitelist = var.atlantis_gh_team_whitelist + atlantis_gh_user = var.atlantis_gh_user + atlantis_repo_whitelist = var.atlantis_repo_whitelist - alb_arn_suffix = "${module.alb.alb_arn_suffix}" - alb_dns_name = "${module.alb.alb_dns_name}" - alb_name = "${module.alb.alb_name}" - alb_zone_id = "${module.alb.alb_zone_id}" + alb_arn_suffix = module.alb.alb_arn_suffix + alb_dns_name = module.alb.alb_dns_name + alb_name = module.alb.alb_name + alb_zone_id = module.alb.alb_zone_id + alb_security_group = module.alb.security_group_id - container_cpu = "${var.atlantis_container_cpu}" - container_memory = "${var.atlantis_container_memory}" + container_cpu = var.atlantis_container_cpu + container_memory = var.atlantis_container_memory - branch = "${var.atlantis_branch}" - parent_zone_id = "${var.parent_zone_id}" - ecs_cluster_arn = "${aws_ecs_cluster.default.arn}" - ecs_cluster_name = "${aws_ecs_cluster.default.name}" - repo_name = "${var.atlantis_repo_name}" - repo_owner = "${var.atlantis_repo_owner}" - private_subnet_ids = ["${module.subnets.private_subnet_ids}"] - security_group_ids = ["${module.vpc.vpc_default_security_group_id}"] - vpc_id = "${module.vpc.vpc_id}" + branch = var.atlantis_branch + parent_zone_id = var.parent_zone_id + ecs_cluster_arn = aws_ecs_cluster.default.arn + ecs_cluster_name = aws_ecs_cluster.default.name + repo_name = var.atlantis_repo_name + repo_owner = var.atlantis_repo_owner + private_subnet_ids = module.subnets.private_subnet_ids + security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_id = module.vpc.vpc_id # Without authentication, both HTTP and HTTPS endpoints are supported - alb_ingress_unauthenticated_listener_arns = ["${module.alb.listener_arns}"] + alb_ingress_unauthenticated_listener_arns = [module.alb.listener_arns] alb_ingress_unauthenticated_listener_arns_count = 2 # All paths are unauthenticated alb_ingress_unauthenticated_paths = ["/*"] - alb_ingress_listener_unauthenticated_priority = "100" + alb_ingress_listener_unauthenticated_priority = 100 alb_ingress_authenticated_paths = [] } diff --git a/examples/without_authentication/outputs.tf b/examples/without_authentication/outputs.tf index dfe3108..12ec479 100644 --- a/examples/without_authentication/outputs.tf +++ b/examples/without_authentication/outputs.tf @@ -1,3 +1,3 @@ output "atlantis_url" { - value = "${module.atlantis.atlantis_url}" + value = module.atlantis.atlantis_url } diff --git a/examples/without_authentication/variables.tf b/examples/without_authentication/variables.tf index d9f42bd..bde7be6 100644 --- a/examples/without_authentication/variables.tf +++ b/examples/without_authentication/variables.tf @@ -1,99 +1,99 @@ variable "namespace" { - type = "string" + type = string description = "Namespace (e.g. `cp` or `cloudposse`)" default = "eg" } variable "stage" { - type = "string" + type = string description = "Stage (e.g. `prod`, `dev`, `staging`)" default = "testing" } variable "name" { - type = "string" + type = string description = "Application or solution name (e.g. `app`)" default = "atlantis" } variable "delimiter" { - type = "string" + type = string default = "-" description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" } variable "attributes" { - type = "list" + type = list(string) default = [] description = "Additional attributes (e.g. `1`)" } variable "tags" { - type = "map" + type = map(string) default = {} description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)" } variable "region" { - type = "string" + type = string description = "AWS Region" default = "us-west-2" } variable "certificate_arn" { - type = "string" + type = string description = "SSL certificate ARN for ALB HTTPS endpoints" } variable "atlantis_gh_team_whitelist" { - type = "string" + type = string description = "Atlantis GitHub team whitelist" default = "engineering:plan,devops:*" } variable "atlantis_gh_user" { - type = "string" + type = string description = "Atlantis GitHub user" default = "examplebot" } variable "atlantis_repo_whitelist" { - type = "list" + type = list(string) description = "Whitelist of repositories Atlantis will accept webhooks from" default = ["github.com/example/*"] } variable "atlantis_repo_name" { - type = "string" + type = string description = "GitHub repository name of the atlantis to be built and deployed to ECS" default = "atlantis" } variable "atlantis_repo_owner" { - type = "string" + type = string description = "GitHub organization containing the Atlantis repository" default = "cloudposse" } variable "atlantis_branch" { - type = "string" + type = string description = "Atlantis branch of the GitHub repository, _e.g._ `master`" default = "master" } variable "atlantis_container_cpu" { - type = "string" + type = number description = "The vCPU setting to control cpu limits of container. (If FARGATE launch type is used below, this must be a supported vCPU size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "256" + default = 256 } variable "atlantis_container_memory" { - type = "string" + type = number description = "The amount of RAM to allow container to use in MB. (If FARGATE launch type is used below, this must be a supported Memory size from the table here: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html)" - default = "512" + default = 512 } variable "parent_zone_id" { - type = "string" + type = string description = "The zone ID where the DNS record for the atlantis `short_name` will be written" } diff --git a/examples/without_authentication/versions.tf b/examples/without_authentication/versions.tf new file mode 100644 index 0000000..9840ed7 --- /dev/null +++ b/examples/without_authentication/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + template = "~> 2.0" + null = "~> 2.0" + local = "~> 1.3" + } +} diff --git a/main.tf b/main.tf index 4d64fa9..c6d8479 100644 --- a/main.tf +++ b/main.tf @@ -1,361 +1,352 @@ -# Pin the `aws` provider -# https://www.terraform.io/docs/configuration/providers.html -# Any non-beta version >= 2.12.0 and < 2.13.0, e.g. 2.12.X -provider "aws" { - version = "~> 2.12.0" -} - -# Terraform -#-------------------------------------------------------------- -terraform { - required_version = "~> 0.11.0" -} - # Data #-------------------------------------------------------------- data "aws_ssm_parameter" "atlantis_gh_token" { - count = "${local.enabled && length(var.github_oauth_token) == 0 ? 1 : 0}" - name = "${local.github_oauth_token_ssm_name}" + count = var.enabled && var.github_oauth_token == "" ? 1 : 0 + name = local.github_oauth_token_ssm_name } data "aws_ssm_parameter" "github_webhooks_token" { - count = "${local.enabled && length(var.github_webhooks_token) == 0 ? 1 : 0}" - name = "${local.github_webhooks_token_ssm_name}" + count = var.enabled && var.github_webhooks_token == "" ? 1 : 0 + name = local.github_webhooks_token_ssm_name } data "aws_kms_key" "chamber_kms_key" { - count = "${local.enabled && length(var.kms_key_id) == 0 ? 1 : 0}" - key_id = "${local.kms_key_id}" + count = var.enabled ? 1 : 0 + key_id = local.kms_key_id } # Locals #-------------------------------------------------------------- locals { - enabled = "${var.enabled == "true" ? true : false}" - atlantis_gh_webhook_secret = "${length(var.atlantis_gh_webhook_secret) > 0 ? var.atlantis_gh_webhook_secret : join("", random_string.atlantis_gh_webhook_secret.*.result)}" - atlantis_webhook_url = "${format(var.atlantis_webhook_format, local.hostname)}" - atlantis_url = "${format(var.atlantis_url_format, local.hostname)}" - attributes = "${concat(list(var.short_name), var.attributes)}" - default_hostname = "${join("", aws_route53_record.default.*.fqdn)}" - hostname = "${length(var.hostname) > 0 ? var.hostname : local.default_hostname}" - kms_key_id = "${length(var.kms_key_id) > 0 ? var.kms_key_id : format("alias/%s-%s-chamber", var.namespace, var.stage)}" + hostname = var.hostname != "" ? var.hostname : local.default_hostname + atlantis_webhook_url = format(var.atlantis_webhook_format, local.hostname) + atlantis_url = format(var.atlantis_url_format, local.hostname) + atlantis_gh_webhook_secret = var.atlantis_gh_webhook_secret != "" ? var.atlantis_gh_webhook_secret : join("", random_string.atlantis_gh_webhook_secret.*.result) + default_hostname = join("", aws_route53_record.default.*.fqdn) + kms_key_id = var.kms_key_id != "" ? var.kms_key_id : format("alias/%s-%s-chamber", var.namespace, var.stage) } # GitHub tokens locals { - github_oauth_token = "${length(join("", data.aws_ssm_parameter.atlantis_gh_token.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_gh_token.*.value) : var.github_oauth_token}" - github_oauth_token_ssm_name = "${length(var.github_oauth_token_ssm_name) > 0 ? var.github_oauth_token_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_gh_token")}" + github_oauth_token = var.github_oauth_token != "" ? var.github_oauth_token : join("", data.aws_ssm_parameter.atlantis_gh_token.*.value) + github_oauth_token_ssm_name = var.github_oauth_token_ssm_name != "" ? var.github_oauth_token_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_gh_token") - github_webhooks_token = "${length(join("", data.aws_ssm_parameter.github_webhooks_token.*.value)) > 0 ? join("", data.aws_ssm_parameter.github_webhooks_token.*.value) : var.github_webhooks_token}" - github_webhooks_token_ssm_name = "${length(var.github_webhooks_token_ssm_name) > 0 ? var.github_webhooks_token_ssm_name : format(var.chamber_format, var.chamber_service, "github_webhooks_token")}" + github_webhooks_token = var.github_webhooks_token != "" ? var.github_webhooks_token : join("", data.aws_ssm_parameter.github_webhooks_token.*.value) + github_webhooks_token_ssm_name = var.github_webhooks_token_ssm_name != "" ? var.github_webhooks_token_ssm_name : format(var.chamber_format, var.chamber_service, "github_webhooks_token" + ) } # Modules #-------------------------------------------------------------- module "ssh_key_pair" { - source = "git::https://github.com/cloudposse/terraform-aws-ssm-tls-ssh-key-pair.git?ref=tags/0.2.0" - enabled = "${local.enabled}" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - attributes = "${local.attributes}" - ssh_private_key_name = "${var.ssh_private_key_name}" - ssh_public_key_name = "${var.ssh_public_key_name}" - ssm_path_prefix = "${var.chamber_service}" + source = "git::https://github.com/cloudposse/terraform-aws-ssm-tls-ssh-key-pair.git?ref=tags/0.4.0" + enabled = var.enabled + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + ssh_private_key_name = var.ssh_private_key_name + ssh_public_key_name = var.ssh_public_key_name + ssm_path_prefix = var.chamber_service + kms_key_id = local.kms_key_id } module "webhooks" { - source = "git::https://github.com/cloudposse/terraform-github-repository-webhooks.git?ref=tags/0.4.0" - github_token = "${local.github_webhooks_token}" - webhook_secret = "${local.atlantis_gh_webhook_secret}" - webhook_url = "${local.atlantis_webhook_url}" - enabled = "${local.enabled}" - github_organization = "${var.repo_owner}" - github_repositories = ["${var.repo_name}"] - events = ["${var.webhook_events}"] -} - -module "web_app" { - source = "git::https://github.com/cloudposse/terraform-aws-ecs-web-app.git?ref=tags/0.23.0" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" - attributes = "${local.attributes}" - - vpc_id = "${var.vpc_id}" + source = "git::https://github.com/cloudposse/terraform-github-repository-webhooks.git?ref=tags/0.5.0" + enabled = var.enabled && var.webhook_enabled + github_token = local.github_webhooks_token + webhook_secret = local.atlantis_gh_webhook_secret + webhook_url = local.atlantis_webhook_url + github_organization = var.repo_owner + github_repositories = [var.repo_name] + events = var.webhook_events +} + +module "ecs_web_app" { + source = "git::https://github.com/cloudposse/terraform-aws-ecs-web-app.git?ref=tags/0.24.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + + region = var.region + vpc_id = var.vpc_id + launch_type = var.launch_type environment = [ { name = "ATLANTIS_ENABLED" - value = "${local.enabled}" - }, + value = var.enabled + } ] - github_webhook_events = ["release"] - webhook_filter_json_path = "$.action" - webhook_filter_match_equals = "published" - - container_image = "${var.default_backend_image}" - container_cpu = "${var.container_cpu}" - container_memory = "${var.container_memory}" + container_image = var.default_backend_image + container_cpu = var.container_cpu + container_memory = var.container_memory - codepipeline_enabled = "${local.enabled}" + container_port = var.atlantis_port - container_port = "${var.atlantis_port}" - - port_mappings = [{ - "containerPort" = "${var.atlantis_port}" - "hostPort" = "${var.atlantis_port}" - "protocol" = "tcp" - }] + port_mappings = [ + { + containerPort = var.atlantis_port + hostPort = var.atlantis_port + protocol = "tcp" + } + ] - desired_count = "${var.desired_count}" + desired_count = var.desired_count - autoscaling_enabled = "${local.enabled}" + autoscaling_enabled = var.autoscaling_enabled autoscaling_dimension = "cpu" - autoscaling_min_capacity = "${var.autoscaling_min_capacity}" - autoscaling_max_capacity = "${var.autoscaling_max_capacity}" - autoscaling_scale_up_adjustment = "1" - autoscaling_scale_up_cooldown = "60" - autoscaling_scale_down_adjustment = "-1" - autoscaling_scale_down_cooldown = "300" - - aws_logs_region = "${var.region}" - ecs_alarms_enabled = "${local.enabled}" - ecs_cluster_arn = "${var.ecs_cluster_arn}" - ecs_cluster_name = "${var.ecs_cluster_name}" - ecs_security_group_ids = ["${var.security_group_ids}"] - ecs_private_subnet_ids = ["${var.private_subnet_ids}"] - - alb_ingress_healthcheck_path = "${var.healthcheck_path}" - - github_oauth_token = "${local.github_oauth_token}" - github_webhooks_token = "${local.github_webhooks_token}" - repo_owner = "${var.repo_owner}" - repo_name = "${var.repo_name}" - branch = "${var.branch}" - build_timeout = "${var.build_timeout}" - badge_enabled = "false" - - codepipeline_s3_bucket_force_destroy = "${var.codepipeline_s3_bucket_force_destroy}" - - alb_target_group_alarms_enabled = "${local.enabled}" - alb_target_group_alarms_3xx_threshold = "25" - alb_target_group_alarms_4xx_threshold = "25" - alb_target_group_alarms_5xx_threshold = "25" - alb_target_group_alarms_response_time_threshold = "0.5" - alb_target_group_alarms_period = "300" - alb_target_group_alarms_evaluation_periods = "1" - alb_name = "${var.alb_name}" - alb_arn_suffix = "${var.alb_arn_suffix}" - alb_security_group = "${var.alb_security_group}" - - alb_target_group_alarms_alarm_actions = ["${var.alb_target_group_alarms_alarm_actions}"] - alb_target_group_alarms_ok_actions = ["${var.alb_target_group_alarms_ok_actions}"] - alb_target_group_alarms_insufficient_data_actions = ["${var.alb_target_group_alarms_insufficient_data_actions}"] - - alb_ingress_authenticated_paths = ["${var.alb_ingress_authenticated_paths}"] - alb_ingress_unauthenticated_paths = ["${var.alb_ingress_unauthenticated_paths}"] - alb_ingress_authenticated_hosts = ["${var.alb_ingress_authenticated_hosts}"] - alb_ingress_unauthenticated_hosts = ["${var.alb_ingress_unauthenticated_hosts}"] - - alb_ingress_listener_authenticated_priority = "${var.alb_ingress_listener_authenticated_priority}" - alb_ingress_listener_unauthenticated_priority = "${var.alb_ingress_listener_unauthenticated_priority}" - - alb_ingress_unauthenticated_listener_arns = "${var.alb_ingress_unauthenticated_listener_arns}" - alb_ingress_unauthenticated_listener_arns_count = "${var.alb_ingress_unauthenticated_listener_arns_count}" - alb_ingress_authenticated_listener_arns = "${var.alb_ingress_authenticated_listener_arns}" - alb_ingress_authenticated_listener_arns_count = "${var.alb_ingress_authenticated_listener_arns_count}" - - authentication_type = "${var.authentication_type}" - authentication_cognito_user_pool_arn = "${local.authentication_cognito_user_pool_arn}" - authentication_cognito_user_pool_client_id = "${local.authentication_cognito_user_pool_client_id}" - authentication_cognito_user_pool_domain = "${local.authentication_cognito_user_pool_domain}" - authentication_oidc_client_id = "${local.authentication_oidc_client_id}" - authentication_oidc_client_secret = "${local.authentication_oidc_client_secret}" - authentication_oidc_issuer = "${var.authentication_oidc_issuer}" - authentication_oidc_authorization_endpoint = "${var.authentication_oidc_authorization_endpoint}" - authentication_oidc_token_endpoint = "${var.authentication_oidc_token_endpoint}" - authentication_oidc_user_info_endpoint = "${var.authentication_oidc_user_info_endpoint}" + autoscaling_min_capacity = var.autoscaling_min_capacity + autoscaling_max_capacity = var.autoscaling_max_capacity + autoscaling_scale_up_adjustment = 1 + autoscaling_scale_up_cooldown = 60 + autoscaling_scale_down_adjustment = -1 + autoscaling_scale_down_cooldown = 300 + + aws_logs_region = var.region + ecs_cluster_arn = var.ecs_cluster_arn + ecs_cluster_name = var.ecs_cluster_name + ecs_security_group_ids = var.security_group_ids + ecs_private_subnet_ids = var.private_subnet_ids + + alb_ingress_healthcheck_path = var.healthcheck_path + + webhook_enabled = var.webhook_enabled + github_webhook_events = ["release"] + webhook_filter_json_path = "$.action" + webhook_filter_match_equals = "published" + + github_oauth_token = local.github_oauth_token + github_webhooks_token = local.github_webhooks_token + + repo_owner = var.repo_owner + repo_name = var.repo_name + branch = var.branch + build_timeout = var.build_timeout + badge_enabled = false + + codepipeline_enabled = var.codepipeline_enabled + codepipeline_s3_bucket_force_destroy = var.codepipeline_s3_bucket_force_destroy + + ecs_alarms_enabled = var.ecs_alarms_enabled + alb_target_group_alarms_enabled = var.alb_target_group_alarms_enabled + alb_target_group_alarms_3xx_threshold = 25 + alb_target_group_alarms_4xx_threshold = 25 + alb_target_group_alarms_5xx_threshold = 25 + alb_target_group_alarms_response_time_threshold = 0.5 + alb_target_group_alarms_period = 300 + alb_target_group_alarms_evaluation_periods = 1 + alb_arn_suffix = var.alb_arn_suffix + alb_security_group = var.alb_security_group + + alb_target_group_alarms_alarm_actions = var.alb_target_group_alarms_alarm_actions + alb_target_group_alarms_ok_actions = var.alb_target_group_alarms_ok_actions + alb_target_group_alarms_insufficient_data_actions = var.alb_target_group_alarms_insufficient_data_actions + + alb_ingress_authenticated_paths = var.alb_ingress_authenticated_paths + alb_ingress_unauthenticated_paths = var.alb_ingress_unauthenticated_paths + alb_ingress_authenticated_hosts = var.alb_ingress_authenticated_hosts + alb_ingress_unauthenticated_hosts = var.alb_ingress_unauthenticated_hosts + + alb_ingress_listener_authenticated_priority = var.alb_ingress_listener_authenticated_priority + alb_ingress_listener_unauthenticated_priority = var.alb_ingress_listener_unauthenticated_priority + + alb_ingress_unauthenticated_listener_arns = var.alb_ingress_unauthenticated_listener_arns + alb_ingress_unauthenticated_listener_arns_count = var.alb_ingress_unauthenticated_listener_arns_count + alb_ingress_authenticated_listener_arns = var.alb_ingress_authenticated_listener_arns + alb_ingress_authenticated_listener_arns_count = var.alb_ingress_authenticated_listener_arns_count + + authentication_type = var.authentication_type + authentication_cognito_user_pool_arn = local.authentication_cognito_user_pool_arn + authentication_cognito_user_pool_client_id = local.authentication_cognito_user_pool_client_id + authentication_cognito_user_pool_domain = local.authentication_cognito_user_pool_domain + authentication_oidc_client_id = local.authentication_oidc_client_id + authentication_oidc_client_secret = local.authentication_oidc_client_secret + authentication_oidc_issuer = var.authentication_oidc_issuer + authentication_oidc_authorization_endpoint = var.authentication_oidc_authorization_endpoint + authentication_oidc_token_endpoint = var.authentication_oidc_token_endpoint + authentication_oidc_user_info_endpoint = var.authentication_oidc_user_info_endpoint } # Resources #-------------------------------------------------------------- resource "aws_route53_record" "default" { - count = "${local.enabled ? 1 : 0}" - zone_id = "${var.parent_zone_id}" - name = "${var.short_name}" + count = var.enabled ? 1 : 0 + zone_id = var.parent_zone_id + name = var.short_name type = "A" alias { - name = "${var.alb_dns_name}" - zone_id = "${var.alb_zone_id}" - evaluate_target_health = "false" + name = var.alb_dns_name + zone_id = var.alb_zone_id + evaluate_target_health = false } } resource "random_string" "atlantis_gh_webhook_secret" { - count = "${local.enabled ? 1 : 0}" - length = "${var.webhook_secret_length}" + count = var.enabled ? 1 : 0 + length = var.webhook_secret_length special = true } resource "aws_ssm_parameter" "atlantis_port" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis server port" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_port")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_port") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_port}" + value = var.atlantis_port } resource "aws_ssm_parameter" "atlantis_atlantis_url" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis URL" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_atlantis_url")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_atlantis_url") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${local.atlantis_url}" + value = local.atlantis_url } resource "aws_ssm_parameter" "atlantis_gh_user" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis GitHub user" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_gh_user")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_gh_user") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_gh_user}" + value = var.atlantis_gh_user } resource "aws_ssm_parameter" "atlantis_gh_team_whitelist" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis GitHub team whitelist" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_gh_team_whitelist")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_gh_team_whitelist") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_gh_team_whitelist}" + value = var.atlantis_gh_team_whitelist } resource "aws_ssm_parameter" "atlantis_gh_webhook_secret" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis GitHub webhook secret" - key_id = "${join("", data.aws_kms_key.chamber_kms_key.*.id)}" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_gh_webhook_secret")}" - overwrite = "${var.overwrite_ssm_parameter}" + key_id = join("", data.aws_kms_key.chamber_kms_key.*.id) + name = format(var.chamber_format, var.chamber_service, "atlantis_gh_webhook_secret") + overwrite = var.overwrite_ssm_parameter type = "SecureString" - value = "${local.atlantis_gh_webhook_secret}" + value = local.atlantis_gh_webhook_secret } resource "aws_ssm_parameter" "atlantis_iam_role_arn" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis IAM role ARN" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_iam_role_arn")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_iam_role_arn") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${module.web_app.task_role_arn}" + value = module.ecs_web_app.ecs_task_role_arn } resource "aws_ssm_parameter" "atlantis_log_level" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Atlantis log level" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_log_level")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_log_level") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_log_level}" + value = var.atlantis_log_level } resource "aws_ssm_parameter" "atlantis_repo_config" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Path to atlantis config file" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_repo_config")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_repo_config") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_repo_config}" + value = var.atlantis_repo_config } resource "aws_ssm_parameter" "atlantis_repo_whitelist" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Whitelist of repositories Atlantis will accept webhooks from" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_repo_whitelist")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_repo_whitelist") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${join(",", var.atlantis_repo_whitelist)}" + value = join(",", var.atlantis_repo_whitelist) } resource "aws_ssm_parameter" "atlantis_wake_word" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 description = "Wake world for Atlantis" - name = "${format(var.chamber_format, var.chamber_service, "atlantis_wake_word")}" - overwrite = "${var.overwrite_ssm_parameter}" + name = format(var.chamber_format, var.chamber_service, "atlantis_wake_word") + overwrite = var.overwrite_ssm_parameter type = "String" - value = "${var.atlantis_wake_word}" + value = var.atlantis_wake_word } resource "aws_ssm_parameter" "atlantis_gh_token" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled && var.github_oauth_token != "" ? 1 : 0 description = "Atlantis GitHub OAuth token" - key_id = "${join("", data.aws_kms_key.chamber_kms_key.*.id)}" - name = "${local.github_oauth_token_ssm_name}" - overwrite = "${var.overwrite_ssm_parameter}" + key_id = join("", data.aws_kms_key.chamber_kms_key.*.id) + name = local.github_oauth_token_ssm_name + overwrite = var.overwrite_ssm_parameter type = "SecureString" - value = "${local.github_oauth_token}" + value = local.github_oauth_token } resource "aws_ssm_parameter" "github_webhooks_token" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled && var.github_webhooks_token != "" ? 1 : 0 description = "GitHub OAuth token with permission to create webhooks" - key_id = "${join("", data.aws_kms_key.chamber_kms_key.*.id)}" - name = "${local.github_webhooks_token_ssm_name}" - overwrite = "${var.overwrite_ssm_parameter}" + key_id = join("", data.aws_kms_key.chamber_kms_key.*.id) + name = local.github_webhooks_token_ssm_name + overwrite = var.overwrite_ssm_parameter type = "SecureString" - value = "${local.github_webhooks_token}" + value = local.github_webhooks_token } resource "aws_security_group_rule" "egress_http" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 cidr_blocks = ["0.0.0.0/0"] from_port = 80 protocol = "tcp" - security_group_id = "${module.web_app.service_security_group_id}" + security_group_id = module.ecs_web_app.ecs_service_security_group_id to_port = 80 type = "egress" } resource "aws_security_group_rule" "egress_https" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 cidr_blocks = ["0.0.0.0/0"] from_port = 443 protocol = "tcp" - security_group_id = "${module.web_app.service_security_group_id}" + security_group_id = module.ecs_web_app.ecs_service_security_group_id to_port = 443 type = "egress" } resource "aws_security_group_rule" "egress_udp_dns" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 cidr_blocks = ["0.0.0.0/0"] from_port = 53 protocol = "udp" - security_group_id = "${module.web_app.service_security_group_id}" + security_group_id = module.ecs_web_app.ecs_service_security_group_id to_port = 53 type = "egress" } resource "aws_security_group_rule" "egress_tcp_dns" { - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 cidr_blocks = ["0.0.0.0/0"] from_port = 53 protocol = "tcp" - security_group_id = "${module.web_app.service_security_group_id}" + security_group_id = module.ecs_web_app.ecs_service_security_group_id to_port = 53 type = "egress" } resource "aws_iam_role_policy_attachment" "default" { - count = "${local.enabled ? 1 : 0}" - role = "${module.web_app.task_role_name}" - policy_arn = "${var.policy_arn}" + count = var.enabled ? 1 : 0 + role = module.ecs_web_app.ecs_task_role_name + policy_arn = var.policy_arn lifecycle { create_before_destroy = true @@ -363,93 +354,118 @@ resource "aws_iam_role_policy_attachment" "default" { } locals { - authentication_cognito_user_pool_arn = "${length(join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_arn.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_arn.*.value) : var.authentication_cognito_user_pool_arn}" - authentication_cognito_user_pool_arn_ssm_name = "${length(var.authentication_cognito_user_pool_arn_ssm_name) > 0 ? var.authentication_cognito_user_pool_arn_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_cognito_user_pool_arn")}" + authentication_cognito_user_pool_arn = var.authentication_cognito_user_pool_arn != "" ? var.authentication_cognito_user_pool_arn : join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_arn.*.value) + + authentication_cognito_user_pool_arn_ssm_name = var.authentication_cognito_user_pool_arn_ssm_name != "" ? var.authentication_cognito_user_pool_arn_ssm_name : format( + var.chamber_format, + var.chamber_service, + "atlantis_cognito_user_pool_arn" + ) + + authentication_cognito_user_pool_client_id = var.authentication_cognito_user_pool_client_id != "" ? var.authentication_cognito_user_pool_client_id : join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_client_id.*.value) + + authentication_cognito_user_pool_client_id_ssm_name = var.authentication_cognito_user_pool_client_id_ssm_name != "" ? var.authentication_cognito_user_pool_client_id_ssm_name : format( + var.chamber_format, + var.chamber_service, + "atlantis_cognito_user_pool_client_id" + ) + + authentication_cognito_user_pool_domain = var.authentication_cognito_user_pool_domain != "" ? var.authentication_cognito_user_pool_domain : join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_domain.*.value) + + authentication_cognito_user_pool_domain_ssm_name = var.authentication_cognito_user_pool_domain_ssm_name != "" ? var.authentication_cognito_user_pool_domain_ssm_name : format( + var.chamber_format, + var.chamber_service, + "atlantis_cognito_user_pool_domain" + ) - authentication_cognito_user_pool_client_id = "${length(join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_client_id.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_client_id.*.value) : var.authentication_cognito_user_pool_client_id}" - authentication_cognito_user_pool_client_id_ssm_name = "${length(var.authentication_cognito_user_pool_client_id_ssm_name) > 0 ? var.authentication_cognito_user_pool_client_id_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_cognito_user_pool_client_id")}" + authentication_oidc_client_id = var.authentication_oidc_client_id != "" ? var.authentication_oidc_client_id : join("", data.aws_ssm_parameter.atlantis_oidc_client_id.*.value) - authentication_cognito_user_pool_domain = "${length(join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_domain.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_cognito_user_pool_domain.*.value) : var.authentication_cognito_user_pool_domain}" - authentication_cognito_user_pool_domain_ssm_name = "${length(var.authentication_cognito_user_pool_domain_ssm_name) > 0 ? var.authentication_cognito_user_pool_domain_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_cognito_user_pool_domain")}" + authentication_oidc_client_id_ssm_name = var.authentication_oidc_client_id_ssm_name != "" ? var.authentication_oidc_client_id_ssm_name : format( + var.chamber_format, + var.chamber_service, + "atlantis_oidc_client_id" + ) - authentication_oidc_client_id = "${length(join("", data.aws_ssm_parameter.atlantis_oidc_client_id.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_oidc_client_id.*.value) : var.authentication_oidc_client_id}" - authentication_oidc_client_id_ssm_name = "${length(var.authentication_oidc_client_id_ssm_name) > 0 ? var.authentication_oidc_client_id_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_oidc_client_id")}" + authentication_oidc_client_secret = var.authentication_oidc_client_secret != "" ? var.authentication_oidc_client_secret : join("", data.aws_ssm_parameter.atlantis_oidc_client_secret.*.value) - authentication_oidc_client_secret = "${length(join("", data.aws_ssm_parameter.atlantis_oidc_client_secret.*.value)) > 0 ? join("", data.aws_ssm_parameter.atlantis_oidc_client_secret.*.value) : var.authentication_oidc_client_secret}" - authentication_oidc_client_secret_ssm_name = "${length(var.authentication_oidc_client_secret_ssm_name) > 0 ? var.authentication_oidc_client_secret_ssm_name : format(var.chamber_format, var.chamber_service, "atlantis_oidc_client_secret")}" + authentication_oidc_client_secret_ssm_name = var.authentication_oidc_client_secret_ssm_name != "" ? var.authentication_oidc_client_secret_ssm_name : format( + var.chamber_format, + var.chamber_service, + "atlantis_oidc_client_secret" + ) } data "aws_ssm_parameter" "atlantis_cognito_user_pool_arn" { - count = "${local.enabled && var.authentication_type == "COGNITO" && length(var.authentication_cognito_user_pool_arn) == 0 ? 1 : 0}" - name = "${local.authentication_cognito_user_pool_arn_ssm_name}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_arn == "" ? 1 : 0 + name = local.authentication_cognito_user_pool_arn_ssm_name } data "aws_ssm_parameter" "atlantis_cognito_user_pool_client_id" { - count = "${local.enabled && var.authentication_type == "COGNITO" && length(var.authentication_cognito_user_pool_client_id) == 0 ? 1 : 0}" - name = "${local.authentication_cognito_user_pool_client_id_ssm_name}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_client_id == "" ? 1 : 0 + name = local.authentication_cognito_user_pool_client_id_ssm_name } data "aws_ssm_parameter" "atlantis_cognito_user_pool_domain" { - count = "${local.enabled && var.authentication_type == "COGNITO" && length(var.authentication_cognito_user_pool_domain) == 0 ? 1 : 0}" - name = "${local.authentication_cognito_user_pool_domain_ssm_name}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_domain == "" ? 1 : 0 + name = local.authentication_cognito_user_pool_domain_ssm_name } data "aws_ssm_parameter" "atlantis_oidc_client_id" { - count = "${local.enabled && var.authentication_type == "OIDC" && length(var.authentication_oidc_client_id) == 0 ? 1 : 0}" - name = "${local.authentication_oidc_client_id_ssm_name}" + count = var.enabled && var.authentication_type == "OIDC" && var.authentication_oidc_client_id == "" ? 1 : 0 + name = local.authentication_oidc_client_id_ssm_name } data "aws_ssm_parameter" "atlantis_oidc_client_secret" { - count = "${local.enabled && var.authentication_type == "OIDC" && length(var.authentication_oidc_client_secret) == 0 ? 1 : 0}" - name = "${local.authentication_oidc_client_secret_ssm_name}" + count = var.enabled && var.authentication_type == "OIDC" && var.authentication_oidc_client_secret == "" ? 1 : 0 + name = local.authentication_oidc_client_secret_ssm_name } resource "aws_ssm_parameter" "atlantis_cognito_user_pool_arn" { - count = "${local.enabled && var.authentication_type == "COGNITO" ? 1 : 0}" - overwrite = "${var.overwrite_ssm_parameter}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_arn != "" ? 1 : 0 + overwrite = var.overwrite_ssm_parameter type = "SecureString" description = "Atlantis Cognito User Pool ARN" - key_id = "${local.kms_key_id}" - name = "${local.authentication_cognito_user_pool_arn_ssm_name}" - value = "${local.authentication_cognito_user_pool_arn}" + key_id = local.kms_key_id + name = local.authentication_cognito_user_pool_arn_ssm_name + value = local.authentication_cognito_user_pool_arn } resource "aws_ssm_parameter" "atlantis_cognito_user_pool_client_id" { - count = "${local.enabled && var.authentication_type == "COGNITO" ? 1 : 0}" - overwrite = "${var.overwrite_ssm_parameter}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_client_id != "" ? 1 : 0 + overwrite = var.overwrite_ssm_parameter type = "SecureString" description = "Atlantis Cognito User Pool Client ID" - key_id = "${local.kms_key_id}" - name = "${local.authentication_cognito_user_pool_client_id_ssm_name}" - value = "${local.authentication_cognito_user_pool_client_id}" + key_id = local.kms_key_id + name = local.authentication_cognito_user_pool_client_id_ssm_name + value = local.authentication_cognito_user_pool_client_id } resource "aws_ssm_parameter" "atlantis_cognito_user_pool_domain" { - count = "${local.enabled && var.authentication_type == "COGNITO" ? 1 : 0}" - overwrite = "${var.overwrite_ssm_parameter}" + count = var.enabled && var.authentication_type == "COGNITO" && var.authentication_cognito_user_pool_domain != "" ? 1 : 0 + overwrite = var.overwrite_ssm_parameter type = "SecureString" description = "Atlantis Cognito User Pool Domain" - key_id = "${local.kms_key_id}" - name = "${local.authentication_cognito_user_pool_domain_ssm_name}" - value = "${local.authentication_cognito_user_pool_domain}" + key_id = local.kms_key_id + name = local.authentication_cognito_user_pool_domain_ssm_name + value = local.authentication_cognito_user_pool_domain } resource "aws_ssm_parameter" "atlantis_oidc_client_id" { - count = "${local.enabled && var.authentication_type == "OIDC" ? 1 : 0}" - overwrite = "${var.overwrite_ssm_parameter}" + count = var.enabled && var.authentication_type == "OIDC" && var.authentication_oidc_client_id != "" ? 1 : 0 + overwrite = var.overwrite_ssm_parameter type = "SecureString" description = "Atlantis OIDC Client ID" - key_id = "${local.kms_key_id}" - name = "${local.authentication_oidc_client_id_ssm_name}" - value = "${local.authentication_oidc_client_id}" + key_id = local.kms_key_id + name = local.authentication_oidc_client_id_ssm_name + value = local.authentication_oidc_client_id } resource "aws_ssm_parameter" "atlantis_oidc_client_secret" { - count = "${local.enabled && var.authentication_type == "OIDC" ? 1 : 0}" - overwrite = "${var.overwrite_ssm_parameter}" + count = var.enabled && var.authentication_type == "OIDC" && var.authentication_oidc_client_secret != "" ? 1 : 0 + overwrite = var.overwrite_ssm_parameter type = "SecureString" description = "Atlantis OIDC Client Secret" - key_id = "${local.kms_key_id}" - name = "${local.authentication_oidc_client_secret_ssm_name}" - value = "${local.authentication_oidc_client_secret}" + key_id = local.kms_key_id + name = local.authentication_oidc_client_secret_ssm_name + value = local.authentication_oidc_client_secret } diff --git a/outputs.tf b/outputs.tf index 9ebad97..83cab60 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,19 +1,270 @@ output "atlantis_ssh_public_key" { description = "Atlantis SSH Public Key" - value = "${module.ssh_key_pair.public_key}" -} - -output "badge_url" { - description = "The URL of the build badge when `badge_enabled` is enabled" - value = "${module.web_app.badge_url}" + value = module.ssh_key_pair.public_key } output "atlantis_url" { description = "The URL endpoint for the atlantis server" - value = "${local.atlantis_url}" + value = local.atlantis_url } output "atlantis_webhook_url" { description = "atlantis webhook URL" - value = "${local.atlantis_webhook_url}" + value = local.atlantis_webhook_url +} + +output "ecr_registry_id" { + value = module.ecs_web_app.ecr_registry_id + description = "Registry ID" +} + +output "ecr_registry_url" { + value = module.ecs_web_app.ecr_registry_url + description = "Registry URL" +} + +output "ecr_repository_name" { + value = module.ecs_web_app.ecr_repository_name + description = "Registry name" +} + +output "alb_ingress_target_group_name" { + description = "ALB Target Group name" + value = module.ecs_web_app.alb_ingress_target_group_name +} + +output "alb_ingress_target_group_arn" { + description = "ALB Target Group ARN" + value = module.ecs_web_app.alb_ingress_target_group_arn +} + +output "alb_ingress_target_group_arn_suffix" { + description = "ALB Target Group ARN suffix" + value = module.ecs_web_app.alb_ingress_target_group_arn_suffix +} + +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.ecs_web_app.container_definition_json +} + +output "container_definition_json_map" { + description = "JSON encoded container definitions for use with other terraform resources such as aws_ecs_task_definition" + value = module.ecs_web_app.container_definition_json_map +} + +output "ecs_exec_role_policy_id" { + description = "The ECS service role policy ID, in the form of `role_name:role_policy_name`" + value = module.ecs_web_app.ecs_exec_role_policy_id +} + +output "ecs_exec_role_policy_name" { + description = "ECS service role name" + value = module.ecs_web_app.ecs_exec_role_policy_name +} + +output "ecs_service_name" { + description = "ECS Service name" + value = module.ecs_web_app.ecs_service_name +} + +output "ecs_service_role_arn" { + description = "ECS Service role ARN" + value = module.ecs_web_app.ecs_service_role_arn +} + +output "ecs_task_exec_role_name" { + description = "ECS Task role name" + value = module.ecs_web_app.ecs_task_exec_role_name +} + +output "ecs_task_exec_role_arn" { + description = "ECS Task exec role ARN" + value = module.ecs_web_app.ecs_task_exec_role_arn +} + +output "ecs_task_role_name" { + description = "ECS Task role name" + value = module.ecs_web_app.ecs_task_role_name +} + +output "ecs_task_role_arn" { + description = "ECS Task role ARN" + value = module.ecs_web_app.ecs_task_role_arn +} + +output "ecs_task_role_id" { + description = "ECS Task role id" + value = module.ecs_web_app.ecs_task_role_id +} + +output "ecs_service_security_group_id" { + description = "Security Group ID of the ECS task" + value = module.ecs_web_app.ecs_service_security_group_id +} + +output "ecs_task_definition_family" { + description = "ECS task definition family" + value = module.ecs_web_app.ecs_task_definition_family +} + +output "ecs_task_definition_revision" { + description = "ECS task definition revision" + value = module.ecs_web_app.ecs_task_definition_revision +} + +output "codebuild_project_name" { + description = "CodeBuild project name" + value = module.ecs_web_app.codebuild_project_name +} + +output "codebuild_project_id" { + description = "CodeBuild project ID" + value = module.ecs_web_app.codebuild_project_id +} + +output "codebuild_role_id" { + description = "CodeBuild IAM Role ID" + value = module.ecs_web_app.codebuild_role_id +} + +output "codebuild_role_arn" { + description = "CodeBuild IAM Role ARN" + value = module.ecs_web_app.codebuild_role_arn +} + +output "codebuild_cache_bucket_name" { + description = "CodeBuild cache S3 bucket name" + value = module.ecs_web_app.codebuild_cache_bucket_name +} + +output "codebuild_cache_bucket_arn" { + description = "CodeBuild cache S3 bucket ARN" + value = module.ecs_web_app.codebuild_cache_bucket_arn +} + +output "codebuild_badge_url" { + description = "The URL of the build badge when badge_enabled is enabled" + value = module.ecs_web_app.codebuild_badge_url +} + +output "codepipeline_id" { + description = "CodePipeline ID" + value = module.ecs_web_app.codepipeline_id +} + +output "codepipeline_arn" { + description = "CodePipeline ARN" + value = module.ecs_web_app.codepipeline_arn +} + +output "codepipeline_webhook_id" { + description = "The CodePipeline webhook's ID" + value = module.ecs_web_app.codepipeline_webhook_id +} + +output "codepipeline_webhook_url" { + description = "The CodePipeline webhook's URL. POST events to this endpoint to trigger the target" + value = module.ecs_web_app.codepipeline_webhook_url + sensitive = true +} + +output "ecs_cloudwatch_autoscaling_scale_up_policy_arn" { + description = "ARN of the scale up policy" + value = module.ecs_web_app.ecs_cloudwatch_autoscaling_scale_up_policy_arn +} + +output "ecs_cloudwatch_autoscaling_scale_down_policy_arn" { + description = "ARN of the scale down policy" + value = module.ecs_web_app.ecs_cloudwatch_autoscaling_scale_down_policy_arn +} + +output "ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id + description = "ECS CPU utilization high CloudWatch metric alarm ID" +} + +output "ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_arn + description = "ECS CPU utilization high CloudWatch metric alarm ARN" +} + +output "ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id + description = "ECS CPU utilization low CloudWatch metric alarm ID" +} + +output "ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_arn + description = "ECS CPU utilization low CloudWatch metric alarm ARN" +} + +output "ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id + description = "ECS Memory utilization high CloudWatch metric alarm ID" +} + +output "ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_arn + description = "ECS Memory utilization high CloudWatch metric alarm ARN" +} + +output "ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id + description = "ECS Memory utilization low CloudWatch metric alarm ID" +} + +output "ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_arn + description = "ECS Memory utilization low CloudWatch metric alarm ARN" +} + +output "httpcode_target_3xx_count_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.httpcode_target_3xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 3xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_3xx_count_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.httpcode_target_3xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 3xx count CloudWatch metric alarm ARN" +} + +output "httpcode_target_4xx_count_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.httpcode_target_4xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 4xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_4xx_count_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.httpcode_target_4xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 4xx count CloudWatch metric alarm ARN" +} + +output "httpcode_target_5xx_count_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.httpcode_target_5xx_count_cloudwatch_metric_alarm_id + description = "ALB Target Group 5xx count CloudWatch metric alarm ID" +} + +output "httpcode_target_5xx_count_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.httpcode_target_5xx_count_cloudwatch_metric_alarm_arn + description = "ALB Target Group 5xx count CloudWatch metric alarm ARN" +} + +output "httpcode_elb_5xx_count_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.httpcode_elb_5xx_count_cloudwatch_metric_alarm_id + description = "ALB 5xx count CloudWatch metric alarm ID" +} + +output "httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.httpcode_elb_5xx_count_cloudwatch_metric_alarm_arn + description = "ALB 5xx count CloudWatch metric alarm ARN" +} + +output "target_response_time_average_cloudwatch_metric_alarm_id" { + value = module.ecs_web_app.target_response_time_average_cloudwatch_metric_alarm_id + description = "ALB Target Group response time average CloudWatch metric alarm ID" +} + +output "target_response_time_average_cloudwatch_metric_alarm_arn" { + value = module.ecs_web_app.target_response_time_average_cloudwatch_metric_alarm_arn + description = "ALB Target Group response time average CloudWatch metric alarm ARN" } diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..442804a --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.test-harness diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..17b2fe7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,43 @@ +TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git +TEST_HARNESS_BRANCH ?= master +TEST_HARNESS_PATH = $(realpath .test-harness) +BATS_ARGS ?= --tap +BATS_LOG ?= test.log + +# Define a macro to run the tests +define RUN_TESTS +@echo "Running tests in $(1)" +@cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS))) +endef + +default: all + +-include Makefile.* + +## Provision the test-harnesss +.test-harness: + [ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@ + +## Initialize the tests +init: .test-harness + +## Install all dependencies (OS specific) +deps:: + @exit 0 + +## Clean up the test harness +clean: + [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH) + +## Run all tests +all: module examples/complete + +## Run basic sanity checks against the module itself +module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions +module: deps + $(call RUN_TESTS, ../) + +## Run tests against example +examples/complete: export TESTS ?= installed lint get-modules get-plugins validate +examples/complete: deps + $(call RUN_TESTS, ../$@) diff --git a/test/Makefile.alpine b/test/Makefile.alpine new file mode 100644 index 0000000..7925b18 --- /dev/null +++ b/test/Makefile.alpine @@ -0,0 +1,5 @@ +ifneq (,$(wildcard /sbin/apk)) +## Install all dependencies for alpine +deps:: init + @apk add --update terraform-docs@cloudposse json2hcl@cloudposse +endif diff --git a/test/src/.gitignore b/test/src/.gitignore new file mode 100644 index 0000000..31b0219 --- /dev/null +++ b/test/src/.gitignore @@ -0,0 +1,2 @@ +.gopath +vendor/ diff --git a/test/src/Gopkg.lock b/test/src/Gopkg.lock new file mode 100644 index 0000000..87bb6bd --- /dev/null +++ b/test/src/Gopkg.lock @@ -0,0 +1,92 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:75d6042fc66aebc974cc49b0c6c7cc3b9adb5f8130fbfa0dbec0820d990afa25" + name = "github.com/gruntwork-io/terratest" + packages = [ + "modules/collections", + "modules/customerrors", + "modules/files", + "modules/logger", + "modules/retry", + "modules/shell", + "modules/ssh", + "modules/terraform", + ] + pruneopts = "UT" + revision = "892abb2c35878d0808101bbfe6559e931dc2d354" + version = "v0.16.0" + +[[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "UT" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + digest = "1:5da8ce674952566deae4dbc23d07c85caafc6cfa815b0b3e03e41979cedb8750" + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + ] + pruneopts = "UT" + revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" + version = "v1.3.0" + +[[projects]] + branch = "master" + digest = "1:831470c2758c8b733941144f2803a0ccad0632c5a767415b777ebd296b5f463e" + name = "golang.org/x/crypto" + packages = [ + "curve25519", + "ed25519", + "ed25519/internal/edwards25519", + "internal/chacha20", + "internal/subtle", + "poly1305", + "ssh", + "ssh/agent", + ] + pruneopts = "UT" + revision = "22d7a77e9e5f409e934ed268692e56707cd169e5" + +[[projects]] + branch = "master" + digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" + name = "golang.org/x/net" + packages = ["context"] + pruneopts = "UT" + revision = "f3200d17e092c607f615320ecaad13d87ad9a2b3" + +[[projects]] + branch = "master" + digest = "1:181f3fd33e620b958b5ab77da177cf775cdcccd7db82963607875fbd09ae995e" + name = "golang.org/x/sys" + packages = [ + "cpu", + "unix", + ] + pruneopts = "UT" + revision = "9cd6430ef91e39e1a0ec0470cf1321a33ef1b887" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/gruntwork-io/terratest/modules/terraform", + "github.com/stretchr/testify/assert", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/test/src/Gopkg.toml b/test/src/Gopkg.toml new file mode 100644 index 0000000..995bac5 --- /dev/null +++ b/test/src/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 0000000..dec7cfb --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,50 @@ +PACKAGE = terraform-aws-ecs-atlantis +GOEXE ?= /usr/bin/go +GOPATH = $(CURDIR)/.gopath +GOBIN = $(GOPATH)/bin +BASE = $(GOPATH)/src/$(PACKAGE) +PATH := $(PATH):$(GOBIN) + +export TF_DATA_DIR ?= $(CURDIR)/.terraform +export TF_CLI_ARGS_init ?= -get-plugins=true +export GOPATH + +.PHONY: all +## Default target +all: test + +ifneq (,$(wildcard /sbin/apk)) +## Install go, if not installed +$(GOEXE): + apk add --update go +endif + +ifeq ($(shell uname -s),Linux) +## Install all `dep`, if not installed +$(GOBIN)/dep: + @mkdir -p $(GOBIN) + @curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh +endif + +## Prepare the GOPATH +$(BASE): $(GOEXE) + @mkdir -p $(dir $@) + @ln -sf $(CURDIR) $@ + +## Download vendor dependencies to vendor/ +$(BASE)/vendor: $(BASE) $(GOBIN)/dep + cd $(BASE) && dep ensure + +.PHONY : init +## Initialize tests +init: $(BASE)/vendor + +.PHONY : test +## Run tests +test: init + cd $(BASE) && go test -v -timeout 30m -run TestExamplesComplete + +.PHONY : clean +## Clean up files +clean: + rm -rf .gopath/ vendor/ $(TF_DATA_DIR) diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go new file mode 100644 index 0000000..3e1f82e --- /dev/null +++ b/test/src/examples_complete_test.go @@ -0,0 +1,208 @@ +package test + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +// Test the Terraform module in examples/complete using Terratest. +func TestExamplesComplete(t *testing.T) { + t.Parallel() + + targets := []string{"module.label", "module.vpc", "module.subnets", "module.alb"} + + // We need to create the ALB first because terraform does not wwait for it to be in the ready state before creating ECS target group + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/complete", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.us-east-2.tfvars"}, + Targets: targets, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer func() { + if r := recover(); r != nil { + terraformOptions.Targets = targets + terraform.Destroy(t, terraformOptions) + terraformOptions.Targets = nil + terraform.Destroy(t, terraformOptions) + assert.Fail(t, fmt.Sprintf("Panicked: %v", r)) + } else { + terraformOptions.Targets = nil + terraform.Destroy(t, terraformOptions) + } + }() + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + terraformOptions.Targets = nil + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.Apply(t, terraformOptions) + + // Run `terraform output` to get the value of an output variable + vpcCidr := terraform.Output(t, terraformOptions, "vpc_cidr") + // Verify we're getting back the outputs we expect + assert.Equal(t, "172.16.0.0/16", vpcCidr) + + // Run `terraform output` to get the value of an output variable + privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs") + // Verify we're getting back the outputs we expect + assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19"}, privateSubnetCidrs) + + // Run `terraform output` to get the value of an output variable + publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs") + // Verify we're getting back the outputs we expect + assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19"}, publicSubnetCidrs) + + // Run `terraform output` to get the value of an output variable + albName := terraform.Output(t, terraformOptions, "alb_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis", albName) + + // Run `terraform output` to get the value of an output variable + albHttpListenerArn := terraform.Output(t, terraformOptions, "alb_http_listener_arn") + // Verify we're getting back the outputs we expect + assert.Contains(t, albHttpListenerArn, "listener/app/eg-test-ecs-atlantis") + + // Run `terraform output` to get the value of an output variable + albIngressTargetGroupName := terraform.Output(t, terraformOptions, "alb_ingress_target_group_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis", albIngressTargetGroupName) + + // Run `terraform output` to get the value of an output variable + albAccessLogsBucketId := terraform.Output(t, terraformOptions, "alb_access_logs_bucket_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-alb-access-logs", albAccessLogsBucketId) + + // Run `terraform output` to get the value of an output variable + containerDefinitionJsonMap := terraform.OutputRequired(t, terraformOptions, "container_definition_json_map") + // Verify we're getting back the outputs we expect + var jsonObject map[string]interface{} + err := json.Unmarshal([]byte(containerDefinitionJsonMap), &jsonObject) + assert.NoError(t, err) + assert.Equal(t, "eg-test-ecs-atlantis", jsonObject["name"]) + assert.Equal(t, "cloudposse/default-backend:0.1.2", jsonObject["image"]) + assert.Equal(t, 512, int((jsonObject["memory"]).(float64))) + assert.Equal(t, 128, int((jsonObject["memoryReservation"]).(float64))) + assert.Equal(t, 256, int((jsonObject["cpu"]).(float64))) + assert.Equal(t, true, jsonObject["essential"]) + assert.Equal(t, false, jsonObject["readonlyRootFilesystem"]) + + // Run `terraform output` to get the value of an output variable + codebuildCacheBucketName := terraform.Output(t, terraformOptions, "codebuild_cache_bucket_name") + // Verify we're getting back the outputs we expect + assert.Contains(t, codebuildCacheBucketName, "eg-test-ecs-atlantis-build") + + // Run `terraform output` to get the value of an output variable + codebuildProjectName := terraform.Output(t, terraformOptions, "codebuild_project_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-build", codebuildProjectName) + + // Run `terraform output` to get the value of an output variable + codebuildRoleId := terraform.Output(t, terraformOptions, "codebuild_role_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-build", codebuildRoleId) + + // Run `terraform output` to get the value of an output variable + codepipelineId := terraform.Output(t, terraformOptions, "codepipeline_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-codepipeline", codepipelineId) + + // Run `terraform output` to get the value of an output variable + ecrRepositoryName := terraform.Output(t, terraformOptions, "ecr_repository_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-ecr", ecrRepositoryName) + + // Run `terraform output` to get the value of an output variable + ecsTaskRoleName := terraform.Output(t, terraformOptions, "ecs_task_role_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-task", ecsTaskRoleName) + + // Run `terraform output` to get the value of an output variable + ecsTaskExecRoleName := terraform.Output(t, terraformOptions, "ecs_task_exec_role_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-exec", ecsTaskExecRoleName) + + // Run `terraform output` to get the value of an output variable + ecsServiceName := terraform.Output(t, terraformOptions, "ecs_service_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis", ecsServiceName) + + // Run `terraform output` to get the value of an output variable + ecsExecRolePolicyName := terraform.Output(t, terraformOptions, "ecs_exec_role_policy_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-exec", ecsExecRolePolicyName) + + // Run `terraform output` to get the value of an output variable + ecsCloudwatchAutoscalingScaleDownPolicyArn := terraform.Output(t, terraformOptions, "ecs_cloudwatch_autoscaling_scale_down_policy_arn") + // Verify we're getting back the outputs we expect + assert.Contains(t, ecsCloudwatchAutoscalingScaleDownPolicyArn, "policyName/eg-test-ecs-atlantis-down") + + // Run `terraform output` to get the value of an output variable + ecsCloudwatchAutoscalingScaleUpPolicyArn := terraform.Output(t, terraformOptions, "ecs_cloudwatch_autoscaling_scale_up_policy_arn") + // Verify we're getting back the outputs we expect + assert.Contains(t, ecsCloudwatchAutoscalingScaleUpPolicyArn, "policyName/eg-test-ecs-atlantis-up") + + // Run `terraform output` to get the value of an output variable + ecsAlarmsCpuUtilizationHighCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "ecs_alarms_cpu_utilization_high_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-cpu-utilization-high", ecsAlarmsCpuUtilizationHighCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + ecsAlarmsCpuUtilizationLowCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "ecs_alarms_cpu_utilization_low_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-cpu-utilization-low", ecsAlarmsCpuUtilizationLowCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + ecsAlarmsMemoryUtilizationHighCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "ecs_alarms_memory_utilization_high_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-memory-utilization-high", ecsAlarmsMemoryUtilizationHighCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + ecsAlarmsMemoryUtilizationLowCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "ecs_alarms_memory_utilization_low_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-memory-utilization-low", ecsAlarmsMemoryUtilizationLowCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + httpcodeElb5xxCountCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "httpcode_elb_5xx_count_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-elb-5xx-count-high", httpcodeElb5xxCountCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + httpcodeTarget3xxCountCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "httpcode_target_3xx_count_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-3xx-count-high", httpcodeTarget3xxCountCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + httpcodeTarget4xxCountCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "httpcode_target_4xx_count_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-4xx-count-high", httpcodeTarget4xxCountCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + httpcodeTarget5xxCountCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "httpcode_target_5xx_count_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-5xx-count-high", httpcodeTarget5xxCountCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + targetResponseTimeAverageCloudwatchMetricAlarmId := terraform.Output(t, terraformOptions, "target_response_time_average_cloudwatch_metric_alarm_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-ecs-atlantis-target-response-high", targetResponseTimeAverageCloudwatchMetricAlarmId) + + // Run `terraform output` to get the value of an output variable + atlantisUrl := terraform.Output(t, terraformOptions, "atlantis_url") + // Verify we're getting back the outputs we expect + assert.Equal(t, "https://ecs-atlantis-test.testing.cloudposse.co", atlantisUrl) + + // Run `terraform output` to get the value of an output variable + atlantisWebhookUrl := terraform.Output(t, terraformOptions, "atlantis_webhook_url") + // Verify we're getting back the outputs we expect + assert.Equal(t, "https://ecs-atlantis-test.testing.cloudposse.co/events", atlantisWebhookUrl) +} diff --git a/variables.tf b/variables.tf index 33bc0f1..c20a8ce 100644 --- a/variables.tf +++ b/variables.tf @@ -1,234 +1,270 @@ +variable "region" { + type = string + description = "AWS Region for S3 bucket" +} + variable "namespace" { - type = "string" + type = string description = "Namespace (e.g. `eg` or `cp`)" + default = "" } variable "stage" { - type = "string" + type = string description = "Stage (e.g. `prod`, `dev`, `staging`)" + default = "" } variable "name" { - type = "string" - description = "Application or solution name (e.g. `app`)" - default = "ecs" + type = string + description = "Name of the application" } variable "delimiter" { - type = "string" + type = string default = "-" - description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" + description = "Delimiter between `namespace`, `stage`, `name` and `attributes`" } variable "attributes" { - type = "list" + type = list(string) + description = "Additional attributes (_e.g._ \"1\")" default = [] - description = "Additional attributes (e.g. `1`)" } variable "tags" { - type = "map" + type = map(string) + description = "Additional tags (_e.g._ { BusinessUnit : ABC })" default = {} - description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)" +} + +variable "launch_type" { + type = string + description = "The ECS launch type (valid options: FARGATE or EC2)" + default = "FARGATE" } variable "default_backend_image" { - type = "string" + type = string default = "cloudposse/default-backend:0.1.2" description = "ECS default (bootstrap) image" } variable "github_oauth_token" { - type = "string" + type = string description = "GitHub OAuth token. If not provided the token is looked up from SSM" default = "" } variable "github_webhooks_token" { - type = "string" + type = string description = "GitHub OAuth Token with permissions to create webhooks. If not provided the token is looked up from SSM" default = "" } variable "github_oauth_token_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `github_oauth_token` if not provided" default = "" } variable "github_webhooks_token_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `github_webhooks_token` if not provided" default = "" } variable "codepipeline_s3_bucket_force_destroy" { + type = bool description = "A boolean that indicates all objects should be deleted from the CodePipeline artifact store S3 bucket so that the bucket can be destroyed without error" default = false } variable "enabled" { - type = "string" - default = "false" + type = bool + default = false description = "Whether to create the resources. Set to `false` to prevent the module from creating any resources" } +variable "codepipeline_enabled" { + type = bool + description = "A boolean to enable/disable AWS Codepipeline and ECR" + default = false +} + variable "build_timeout" { - default = 5 + type = number + default = 10 description = "How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed." } variable "branch" { - type = "string" + type = string default = "master" description = "Atlantis branch of the GitHub repository, _e.g._ `master`" } variable "repo_name" { - type = "string" + type = string description = "GitHub repository name of the atlantis to be built and deployed to ECS." } variable "repo_owner" { - type = "string" + type = string description = "GitHub organization containing the Atlantis repository" } variable "atlantis_repo_config" { - type = "string" + type = string description = "Path to atlantis server-side repo config file (https://www.runatlantis.io/docs/server-side-repo-config.html)" default = "atlantis-repo-config.yaml" } variable "atlantis_repo_whitelist" { - type = "list" + type = list(string) description = "Whitelist of repositories Atlantis will accept webhooks from" default = [] } +variable "autoscaling_enabled" { + type = bool + description = "A boolean to enable/disable Autoscaling policy for ECS Service" + default = false +} + variable "healthcheck_path" { - type = "string" + type = string description = "Healthcheck path" default = "/healthz" } variable "chamber_format" { + type = string default = "/%s/%s" description = "Format to store parameters in SSM, for consumption with chamber" } variable "chamber_service" { + type = string default = "atlantis" description = "SSM parameter service name for use with chamber. This is used in chamber_format where /$chamber_service/$parameter would be the default." } variable "desired_count" { - type = "string" + type = number description = "Atlantis desired number of tasks" - default = "1" + default = 1 } variable "short_name" { - description = "Alantis Short DNS name (E.g. `atlantis`)" + type = string + description = "Alantis short DNS name (e.g. `atlantis`)" default = "atlantis" } variable "hostname" { - type = "string" + type = string description = "Atlantis URL" default = "" } variable "atlantis_gh_user" { - type = "string" + type = string description = "Atlantis GitHub user" } variable "atlantis_gh_team_whitelist" { - type = "string" + type = string description = "Atlantis GitHub team whitelist" default = "" } variable "atlantis_gh_webhook_secret" { - type = "string" + type = string description = "Atlantis GitHub webhook secret" default = "" } variable "atlantis_log_level" { - type = "string" + type = string description = "Atlantis log level" default = "info" } variable "atlantis_port" { - type = "string" + type = number description = "Atlantis container port" - default = "4141" + default = 4141 } variable "atlantis_wake_word" { - type = "string" - description = "Wake world for Atlantis" + type = string + description = "Wake world for atlantis" default = "atlantis" } variable "atlantis_webhook_format" { - type = "string" + type = string default = "https://%s/events" description = "Template for the Atlantis webhook URL which is populated with the hostname" } variable "atlantis_url_format" { - type = "string" + type = string default = "https://%s" description = "Template for the Atlantis URL which is populated with the hostname" } variable "autoscaling_min_capacity" { - type = "string" + type = number description = "Atlantis minimum tasks to run" - default = "1" + default = 1 } variable "autoscaling_max_capacity" { - type = "string" + type = number description = "Atlantis maximum tasks to run" - default = "1" + default = 1 } variable "container_cpu" { - type = "string" + type = number description = "Atlantis CPUs per task" - default = "256" + default = 256 } variable "container_memory" { - type = "string" + type = number description = "Atlantis memory per task" - default = "512" + default = 512 } variable "policy_arn" { - type = "string" + type = string default = "arn:aws:iam::aws:policy/AdministratorAccess" description = "Permission to grant to atlantis server" } variable "kms_key_id" { - type = "string" + type = string default = "" description = "KMS key ID used to encrypt SSM SecureString parameters" } +variable "webhook_enabled" { + type = bool + description = "Set to false to prevent the module from creating any webhook resources" + default = true +} + variable "webhook_secret_length" { + type = number default = 32 description = "GitHub webhook secret length" } variable "webhook_events" { - type = "list" + type = list(string) description = "A list of events which should trigger the webhook." default = [ @@ -241,251 +277,300 @@ variable "webhook_events" { } variable "ssh_private_key_name" { - type = "string" + type = string default = "atlantis_ssh_private_key" description = "Atlantis SSH private key name" } variable "ssh_public_key_name" { - type = "string" + type = string default = "atlantis_ssh_public_key" description = "Atlantis SSH public key name" } variable "vpc_id" { - type = "string" + type = string description = "VPC ID for the ECS Cluster" } -variable "alb_name" { - type = "string" - description = "The Name of the ALB" -} - variable "alb_arn_suffix" { - type = "string" + type = string description = "The ARN suffix of the ALB" } variable "alb_security_group" { - type = "string" + type = string description = "Security group of the ALB" } variable "alb_target_group_alarms_alarm_actions" { - type = "list" + type = list(string) description = "A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state." default = [] } variable "alb_target_group_alarms_ok_actions" { - type = "list" + type = list(string) description = "A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an OK state from any other state." default = [] } variable "alb_target_group_alarms_insufficient_data_actions" { - type = "list" + type = list(string) description = "A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state." default = [] } +variable "ecs_alarms_cpu_utilization_high_alarm_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High Alarm action" + default = [] +} + +variable "ecs_alarms_cpu_utilization_high_ok_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization High OK action" + default = [] +} + +variable "ecs_alarms_cpu_utilization_low_alarm_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low Alarm action" + default = [] +} + +variable "ecs_alarms_cpu_utilization_low_ok_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on CPU Utilization Low OK action" + default = [] +} + +variable "ecs_alarms_memory_utilization_high_alarm_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High Alarm action" + default = [] +} + +variable "ecs_alarms_memory_utilization_high_ok_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization High OK action" + default = [] +} + +variable "ecs_alarms_memory_utilization_low_alarm_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low Alarm action" + default = [] +} + +variable "ecs_alarms_memory_utilization_low_ok_actions" { + type = list(string) + description = "A list of ARNs (i.e. SNS Topic ARN) to notify on Memory Utilization Low OK action" + default = [] +} + variable "alb_dns_name" { - type = "string" + type = string description = "DNS name of ALB" } variable "alb_zone_id" { - type = "string" + type = string description = "The ID of the zone in which ALB is provisioned" } variable "ecs_cluster_name" { - type = "string" + type = string description = "Name of the ECS cluster to deploy Atlantis" } variable "ecs_cluster_arn" { - type = "string" + type = string description = "ARN of the ECS cluster to deploy Atlantis" } variable "security_group_ids" { - type = "list" + type = list(string) default = [] description = "Additional Security Group IDs to allow into ECS Service." } variable "private_subnet_ids" { - type = "list" + type = list(string) default = [] description = "The private subnet IDs" } -variable "region" { - type = "string" - description = "AWS Region for Atlantis deployment" - default = "us-west-2" -} - variable "parent_zone_id" { - type = "string" + type = string description = "The zone ID where the DNS record for the `short_name` will be written" default = "" } variable "overwrite_ssm_parameter" { - type = "string" - default = "true" + type = bool + default = true description = "Whether to overwrite an existing SSM parameter" } variable "alb_ingress_listener_unauthenticated_priority" { - type = "string" - default = "50" + type = number + default = 50 description = "The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority" } variable "alb_ingress_listener_authenticated_priority" { - type = "string" - default = "100" + type = number + default = 100 description = "The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority" } variable "alb_ingress_unauthenticated_hosts" { - type = "list" + type = list(string) default = [] description = "Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined)" } variable "alb_ingress_authenticated_hosts" { - type = "list" + type = list(string) default = [] description = "Authenticated hosts to match in Hosts header (a maximum of 1 can be defined)" } variable "alb_ingress_unauthenticated_paths" { - type = "list" + type = list(string) default = ["/events"] description = "Unauthenticated path pattern to match (a maximum of 1 can be defined)" } variable "alb_ingress_authenticated_paths" { - type = "list" + type = list(string) default = ["/*"] description = "Authenticated path pattern to match (a maximum of 1 can be defined)" } variable "alb_ingress_unauthenticated_listener_arns" { - type = "list" + type = list(string) default = [] description = "A list of unauthenticated ALB listener ARNs to attach ALB listener rules to" } variable "alb_ingress_unauthenticated_listener_arns_count" { - type = "string" - default = "0" + type = number + default = 0 description = "The number of unauthenticated ARNs in `alb_ingress_unauthenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed" } variable "alb_ingress_authenticated_listener_arns" { - type = "list" + type = list(string) default = [] description = "A list of authenticated ALB listener ARNs to attach ALB listener rules to" } variable "alb_ingress_authenticated_listener_arns_count" { - type = "string" - default = "0" + type = number + default = 0 description = "The number of authenticated ARNs in `alb_ingress_authenticated_listener_arns`. This is necessary to work around a limitation in Terraform where counts cannot be computed" } variable "authentication_type" { - type = "string" + type = string default = "" description = "Authentication type. Supported values are `COGNITO` and `OIDC`" } variable "authentication_cognito_user_pool_arn" { - type = "string" + type = string description = "Cognito User Pool ARN" default = "" } variable "authentication_cognito_user_pool_client_id" { - type = "string" + type = string description = "Cognito User Pool Client ID" default = "" } variable "authentication_cognito_user_pool_domain" { - type = "string" + type = string description = "Cognito User Pool Domain. The User Pool Domain should be set to the domain prefix (`xxx`) instead of full domain (https://xxx.auth.us-west-2.amazoncognito.com)" default = "" } variable "authentication_oidc_client_id" { - type = "string" + type = string description = "OIDC Client ID" default = "" } variable "authentication_oidc_client_secret" { - type = "string" + type = string description = "OIDC Client Secret" default = "" } variable "authentication_oidc_issuer" { - type = "string" + type = string description = "OIDC Issuer" default = "" } variable "authentication_oidc_authorization_endpoint" { - type = "string" + type = string description = "OIDC Authorization Endpoint" default = "" } variable "authentication_oidc_token_endpoint" { - type = "string" + type = string description = "OIDC Token Endpoint" default = "" } variable "authentication_oidc_user_info_endpoint" { - type = "string" + type = string description = "OIDC User Info Endpoint" default = "" } variable "authentication_cognito_user_pool_arn_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `authentication_cognito_user_pool_arn` if not provided" default = "" } variable "authentication_cognito_user_pool_client_id_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `authentication_cognito_user_pool_client_id` if not provided" default = "" } variable "authentication_cognito_user_pool_domain_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `authentication_cognito_user_pool_domain` if not provided" default = "" } variable "authentication_oidc_client_id_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `authentication_oidc_client_id` if not provided" default = "" } variable "authentication_oidc_client_secret_ssm_name" { - type = "string" + type = string description = "SSM param name to lookup `authentication_oidc_client_secret` if not provided" default = "" } + +variable "alb_target_group_alarms_enabled" { + type = bool + description = "A boolean to enable/disable CloudWatch Alarms for ALB Target metrics" + default = false +} + +variable "ecs_alarms_enabled" { + type = bool + description = "A boolean to enable/disable CloudWatch Alarms for ECS Service metrics" + default = false +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..9840ed7 --- /dev/null +++ b/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + template = "~> 2.0" + null = "~> 2.0" + local = "~> 1.3" + } +}