Removes modules/task-service in favor of using modules/service for the analytics package. I originally created modules/task-service as a workaround to avoid needing to do this work, before I realized how easy it would be!
Adds enable_load_balancer to enable the ability to avoid deploying a load balancer
Adds count = var.enable_load_balancer ? 1 : 0 to a every load balancer and WAF resource
Amazing Discovery!
In older versions of terraform, adding a count to a resource would force you to do a terraform state mvor a moved block to keep the resource intact. Apparently in newer versions of terraform, this is no longer the case!!! It now automatically detects that you have moved a resource. That detection looks like so:
# module.service.aws_lb.alb has moved to module.service.aws_lb.alb[0]
resource "aws_lb" "alb" {
id = "..."
name = "api-dev"
tags = {}
# (25 unchanged attributes hidden)
# (5 unchanged blocks hidden)
}
Beacuse of this, this PR was MUCH EASIER than I thought it would be! I'm so happy that we are using a recent version of terraform!
terraform plan inside of infra/analytics/service
```
terraform apply -var="environment_name=dev"
data.terraform_remote_state.current_image_tag[0]: Reading...
data.aws_iam_policy.app_db_access_policy[0]: Reading...
data.aws_vpc.network: Reading...
module.service.data.aws_ecr_repository.app[0]: Reading...
module.service.data.aws_region.current: Reading...
data.aws_rds_cluster.db_cluster[0]: Reading...
module.service.data.aws_caller_identity.current: Reading...
data.aws_iam_policy.migrator_db_access_policy[0]: Reading...
aws_scheduler_schedule_group.sprint_reports: Refreshing state... [id=analytics-dev-sprint-reports]
module.service.data.aws_region.current: Read complete after 0s [id=us-east-1]
aws_cloudwatch_log_group.sprint_reports: Refreshing state... [id=/aws/vendedlogs/states/analytics-dev-sprint-reports20240402190032717900000001]
module.service.aws_cloudwatch_log_group.service_logs: Refreshing state... [id=service/analytics-dev]
module.service.data.aws_caller_identity.current: Read complete after 0s [id=315341936575]
module.service.aws_ecs_cluster.cluster: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:cluster/analytics-dev]
module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Reading...
module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Read complete after 0s [id=597844978]
module.service.aws_iam_role.app_service: Refreshing state... [id=analytics-dev-app]
module.service.aws_iam_role.task_executor: Refreshing state... [id=analytics-dev-task-executor]
data.aws_rds_cluster.db_cluster[0]: Read complete after 0s [id=analytics-dev]
module.service.aws_iam_role.migrator_task[0]: Refreshing state... [id=analytics-dev-migrator]
data.terraform_remote_state.current_image_tag[0]: Read complete after 1s
module.service.data.aws_ecr_repository.app[0]: Read complete after 1s [id=simpler-grants-gov-analytics]
module.service.aws_ecs_task_definition.app: Refreshing state... [id=analytics-dev]
module.service.data.aws_iam_policy_document.task_executor: Reading...
module.service.data.aws_iam_policy_document.task_executor: Read complete after 0s [id=3572404559]
module.service.aws_iam_role_policy.task_executor: Refreshing state... [id=analytics-dev-task-executor:analytics-dev-task-executor-role-policy]
data.aws_vpc.network: Read complete after 1s [id=vpc-08f522c5cc442d126]
data.aws_subnets.public: Reading...
data.aws_subnets.private: Reading...
module.service.aws_security_group.app: Refreshing state... [id=sg-0ed2e3fe9a482683c]
data.aws_subnets.public: Read complete after 0s [id=us-east-1]
data.aws_subnets.private: Read complete after 0s [id=us-east-1]
module.service.aws_vpc_security_group_ingress_rule.db_ingress_from_service[0]: Refreshing state... [id=sgr-005d1c8947c789bd0]
aws_sfn_state_machine.sprint_reports: Refreshing state... [id=arn:aws:states:us-east-1:315341936575:stateMachine:analytics-dev-sprint-reports]
module.service.aws_ecs_service.app: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:service/analytics-dev/analytics-dev]
aws_scheduler_schedule.sprint_reports: Refreshing state... [id=analytics-dev-sprint-reports/analytics-dev-sprint-reports]
data.aws_iam_policy.app_db_access_policy[0]: Read complete after 2s [id=arn:aws:iam::315341936575:policy/analytics-dev-app-access]
module.service.aws_iam_role_policy_attachment.app_service_db_access[0]: Refreshing state... [id=analytics-dev-app-20240328214813228600000005]
data.aws_iam_policy.migrator_db_access_policy[0]: Read complete after 2s [id=arn:aws:iam::315341936575:policy/analytics-dev-migrator-access]
module.service.aws_iam_role_policy_attachment.migrator_db_access[0]: Refreshing state... [id=analytics-dev-migrator-20240328214813227300000004]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
~ update in-place
-/+ destroy and then create replacement
<= read (data resources)
Terraform will perform the following actions:
# aws_sfn_state_machine.sprint_reports will be updated in-place
~ resource "aws_sfn_state_machine" "sprint_reports" {
~ definition = jsonencode(
{
- StartAt = "ExecuteECSTask"
- States = {
- ExecuteECSTask = {
- End = true
- Parameters = {
- Cluster = "arn:aws:ecs:us-east-1:315341936575:cluster/analytics-dev"
- LaunchType = "FARGATE"
- NetworkConfiguration = {
- AwsvpcConfiguration = {
- SecurityGroups = [
- "sg-0ed2e3fe9a482683c",
]
- Subnets = [
- "subnet-0a5ea667d3751639f",
- "subnet-068ede7dcfd9469ab",
- "subnet-019f469ba97dc6ec7",
]
}
}
- Overrides = {
- ContainerOverrides = [
- {
- Command = [
- "make",
- "gh-data-export",
- "sprint-reports",
]
- Environment = [
- {
- Name = "PY_RUN_APPROACH"
- Value = "local"
},
- {
- Name = "SPRINT_FILE"
- Value = "/tmp/sprint-data.json"
},
- {
- Name = "ISSUE_FILE"
- Value = "/tmp/issue-data.json"
},
- {
- Name = "OUTPUT_DIR"
- Value = "/tmp/"
},
]
- Name = "analytics-dev"
},
]
}
- TaskDefinition = "arn:aws:ecs:us-east-1:315341936575:task-definition/analytics-dev:29"
}
- Resource = "arn:aws:states:::ecs:runTask.sync"
- Type = "Task"
}
}
}
) -> (known after apply)
id = "arn:aws:states:us-east-1:315341936575:stateMachine:analytics-dev-sprint-reports"
name = "analytics-dev-sprint-reports"
tags = {}
# (11 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# module.service.data.aws_iam_policy_document.access_logs_put_access will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "access_logs_put_access" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "s3:PutObject",
]
+ effect = "Allow"
+ resources = [
+ (known after apply),
+ (known after apply),
]
+ principals {
+ identifiers = [
+ "arn:aws:iam::127311923021:root",
]
+ type = "AWS"
}
}
+ statement {
+ actions = [
+ "s3:*",
]
+ effect = "Deny"
+ resources = [
+ (known after apply),
+ (known after apply),
]
+ sid = "AllowSSLRequestsOnly"
+ condition {
+ test = "Bool"
+ values = [
+ "false",
]
+ variable = "aws:SecureTransport"
}
+ principals {
+ identifiers = [
+ "*",
]
+ type = "AWS"
}
}
}
# module.service.data.aws_iam_policy_document.general_purpose_put_access will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "general_purpose_put_access" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "s3:*",
]
+ effect = "Allow"
+ resources = [
+ (known after apply),
+ (known after apply),
]
+ principals {
+ identifiers = [
+ "arn:aws:iam::315341936575:role/analytics-dev-app",
]
+ type = "AWS"
}
}
+ statement {
+ actions = [
+ "s3:*",
]
+ effect = "Deny"
+ resources = [
+ (known after apply),
+ (known after apply),
]
+ sid = "AllowSSLRequestsOnly"
+ condition {
+ test = "Bool"
+ values = [
+ "false",
]
+ variable = "aws:SecureTransport"
}
+ principals {
+ identifiers = [
+ "*",
]
+ type = "AWS"
}
}
}
# module.service.aws_ecs_service.app will be updated in-place
~ resource "aws_ecs_service" "app" {
id = "arn:aws:ecs:us-east-1:315341936575:service/analytics-dev/analytics-dev"
name = "analytics-dev"
tags = {}
~ task_definition = "arn:aws:ecs:us-east-1:315341936575:task-definition/analytics-dev:29" -> (known after apply)
# (15 unchanged attributes hidden)
# (3 unchanged blocks hidden)
}
# module.service.aws_ecs_task_definition.app must be replaced
-/+ resource "aws_ecs_task_definition" "app" {
~ arn = "arn:aws:ecs:us-east-1:315341936575:task-definition/analytics-dev:29" -> (known after apply)
~ arn_without_revision = "arn:aws:ecs:us-east-1:315341936575:task-definition/analytics-dev" -> (known after apply)
~ container_definitions = jsonencode(
[
- {
- cpu = 1024
- environment = [
- {
- name = "ACTION"
- value = "show-results"
},
- {
- name = "AWS_REGION"
- value = "us-east-1"
},
- {
- name = "DB_HOST"
- value = "analytics-dev.cluster-crj70bc9j3t7.us-east-1.rds.amazonaws.com"
},
- {
- name = "DB_NAME"
- value = "app"
},
- {
- name = "DB_PORT"
- value = "5432"
},
- {
- name = "DB_SCHEMA"
- value = "analytics"
},
- {
- name = "DB_USER"
- value = "app"
},
- {
- name = "PORT"
- value = "8000"
},
]
- essential = true
- image = "315341936575.dkr.ecr.us-east-1.amazonaws.com/simpler-grants-gov-analytics:58971a07c4956ad282182443a509354a40e92721"
- linuxParameters = {
- capabilities = {
- add = []
- drop = [
- "ALL",
]
}
- initProcessEnabled = true
}
- logConfiguration = {
- logDriver = "awslogs"
- options = {
- awslogs-group = "service/analytics-dev"
- awslogs-region = "us-east-1"
- awslogs-stream-prefix = "analytics-dev"
}
}
- memory = 2048
- mountPoints = []
- name = "analytics-dev"
- portMappings = []
- readonlyRootFilesystem = true
- secrets = [
- {
- name = "ANALYTICS_REPORTING_CHANNEL_ID"
- valueFrom = "/analytics/dev/reporting-channel-id"
},
- {
- name = "ANALYTICS_SLACK_BOT_TOKEN"
- valueFrom = "/analytics/dev/slack-bot-token"
},
- {
- name = "GH_TOKEN"
- valueFrom = "/analytics/dev/github-token"
},
]
- systemControls = []
- volumesFrom = []
},
] # forces replacement
) -> (known after apply) # forces replacement
~ id = "analytics-dev" -> (known after apply)
~ revision = 29 -> (known after apply)
- tags = {} -> null
# (11 unchanged attributes hidden)
}
# module.service.aws_s3_bucket.access_logs will be created
+ resource "aws_s3_bucket" "access_logs" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = (known after apply)
+ bucket_domain_name = (known after apply)
+ bucket_prefix = "analytics-dev-access-logs"
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = {
+ "description" = "Application resources created in dev environment"
+ "environment" = "dev"
+ "owner" = "navapbc"
+ "project" = "simpler-grants-gov"
+ "repository" = "https://github.com/HHS/simpler-grants-gov"
+ "terraform" = "true"
+ "terraform_workspace" = "default"
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
# module.service.aws_s3_bucket.general_purpose will be created
+ resource "aws_s3_bucket" "general_purpose" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = (known after apply)
+ bucket_domain_name = (known after apply)
+ bucket_prefix = "analytics-dev-general-purpose"
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = {
+ "description" = "Application resources created in dev environment"
+ "environment" = "dev"
+ "owner" = "navapbc"
+ "project" = "simpler-grants-gov"
+ "repository" = "https://github.com/HHS/simpler-grants-gov"
+ "terraform" = "true"
+ "terraform_workspace" = "default"
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
# module.service.aws_s3_bucket_lifecycle_configuration.access_logs will be created
+ resource "aws_s3_bucket_lifecycle_configuration" "access_logs" {
+ bucket = (known after apply)
+ id = (known after apply)
+ rule {
+ id = "AbortIncompleteUpload"
+ status = "Enabled"
+ abort_incomplete_multipart_upload {
+ days_after_initiation = 7
}
}
+ rule {
+ id = "StorageClass"
+ status = "Enabled"
+ transition {
+ days = 30
+ storage_class = "STANDARD_IA"
# (1 unchanged attribute hidden)
}
+ transition {
+ days = 60
+ storage_class = "GLACIER"
# (1 unchanged attribute hidden)
}
}
+ rule {
+ id = "Expiration"
+ status = "Enabled"
+ expiration {
+ days = 2555
+ expired_object_delete_marker = (known after apply)
}
}
}
# module.service.aws_s3_bucket_lifecycle_configuration.general_purpose will be created
+ resource "aws_s3_bucket_lifecycle_configuration" "general_purpose" {
+ bucket = (known after apply)
+ id = (known after apply)
+ rule {
+ id = "AbortIncompleteUpload"
+ status = "Enabled"
+ abort_incomplete_multipart_upload {
+ days_after_initiation = 7
}
}
}
# module.service.aws_s3_bucket_policy.access_logs will be created
+ resource "aws_s3_bucket_policy" "access_logs" {
+ bucket = (known after apply)
+ id = (known after apply)
+ policy = (known after apply)
}
# module.service.aws_s3_bucket_policy.general_purpose will be created
+ resource "aws_s3_bucket_policy" "general_purpose" {
+ bucket = (known after apply)
+ id = (known after apply)
+ policy = (known after apply)
}
# module.service.aws_s3_bucket_public_access_block.access_logs will be created
+ resource "aws_s3_bucket_public_access_block" "access_logs" {
+ block_public_acls = true
+ block_public_policy = true
+ bucket = (known after apply)
+ id = (known after apply)
+ ignore_public_acls = true
+ restrict_public_buckets = true
}
# module.service.aws_s3_bucket_public_access_block.general_purpose will be created
+ resource "aws_s3_bucket_public_access_block" "general_purpose" {
+ block_public_acls = true
+ block_public_policy = true
+ bucket = (known after apply)
+ id = (known after apply)
+ ignore_public_acls = true
+ restrict_public_buckets = true
}
# module.service.aws_s3_bucket_server_side_encryption_configuration.encryption will be created
+ resource "aws_s3_bucket_server_side_encryption_configuration" "encryption" {
+ bucket = (known after apply)
+ id = (known after apply)
+ rule {
+ bucket_key_enabled = true
+ apply_server_side_encryption_by_default {
+ sse_algorithm = "aws:kms"
# (1 unchanged attribute hidden)
}
}
}
# module.service.aws_s3_bucket_server_side_encryption_configuration.general_purpose_encryption will be created
+ resource "aws_s3_bucket_server_side_encryption_configuration" "general_purpose_encryption" {
+ bucket = (known after apply)
+ id = (known after apply)
+ rule {
+ bucket_key_enabled = true
+ apply_server_side_encryption_by_default {
+ sse_algorithm = "aws:kms"
# (1 unchanged attribute hidden)
}
}
}
# module.service.aws_security_group.alb will be created
+ resource "aws_security_group" "alb" {
+ arn = (known after apply)
+ description = "Allow TCP traffic to application load balancer"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow all outgoing traffic"
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = (known after apply)
+ name = (known after apply)
+ name_prefix = "analytics-dev-alb"
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags_all = {
+ "description" = "Application resources created in dev environment"
+ "environment" = "dev"
+ "owner" = "navapbc"
+ "project" = "simpler-grants-gov"
+ "repository" = "https://github.com/HHS/simpler-grants-gov"
+ "terraform" = "true"
+ "terraform_workspace" = "default"
}
+ vpc_id = "vpc-08f522c5cc442d126"
}
# module.service.aws_security_group.app will be updated in-place
~ resource "aws_security_group" "app" {
id = "sg-0ed2e3fe9a482683c"
~ ingress = [
+ {
+ cidr_blocks = []
+ description = "Allow HTTP traffic to application container port"
+ from_port = 8000
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = (known after apply)
+ self = false
+ to_port = 8000
},
]
name = "analytics-dev-app20240328231535754500000001"
tags = {}
# (8 unchanged attributes hidden)
}
# module.service.aws_security_group_rule.http_ingress will be created
+ resource "aws_security_group_rule" "http_ingress" {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow HTTP traffic from public internet"
+ from_port = 80
+ id = (known after apply)
+ protocol = "tcp"
+ security_group_id = (known after apply)
+ security_group_rule_id = (known after apply)
+ self = false
+ source_security_group_id = (known after apply)
+ to_port = 80
+ type = "ingress"
}
Plan: 13 to add, 3 to change, 1 to destroy.
```
terraform plan inside of infra/api/service
```
terraform plan -var="environment_name=dev"
data.terraform_remote_state.current_image_tag[0]: Reading...
data.aws_iam_policy.migrator_db_access_policy[0]: Reading...
data.aws_vpc.network: Reading...
module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Reading...
data.aws_rds_cluster.db_cluster[0]: Reading...
aws_scheduler_schedule_group.copy_oracle_data: Refreshing state... [id=api-dev-copy-oracle-data]
module.service.aws_cloudwatch_log_group.WafWebAclLoggroup[0]: Refreshing state... [id=aws-waf-logs-wafv2-web-acl-api-dev]
module.service.aws_ecs_cluster.cluster: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:cluster/api-dev]
aws_cloudwatch_log_group.copy_oracle_data: Refreshing state... [id=/aws/vendedlogs/states/api-dev-copy-oracle-data20240405180135310900000001]
module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Read complete after 0s [id=597844978]
module.service.aws_s3_bucket.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001]
data.aws_iam_policy.app_db_access_policy[0]: Reading...
module.service.aws_cloudwatch_log_group.service_logs: Refreshing state... [id=service/api-dev]
module.service.data.aws_caller_identity.current: Reading...
module.monitoring.aws_cloudwatch_log_metric_filter.service_error_filter: Refreshing state... [id=service-error-filter]
module.monitoring.aws_sns_topic.this: Refreshing state... [id=arn:aws:sns:us-east-1:315341936575:api-dev-monitoring]
module.service.data.aws_caller_identity.current: Read complete after 0s [id=315341936575]
module.service.data.aws_region.current: Reading...
module.service.data.aws_region.current: Read complete after 0s [id=us-east-1]
module.service.aws_s3_bucket.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003]
data.aws_rds_cluster.db_cluster[0]: Read complete after 0s [id=api-dev]
module.service.data.aws_ecr_repository.app[0]: Reading...
data.terraform_remote_state.current_image_tag[0]: Read complete after 1s
module.service.aws_iam_role.app_service: Refreshing state... [id=api-dev-app]
module.service.aws_iam_role.task_executor: Refreshing state... [id=api-dev-task-executor]
module.service.aws_wafv2_web_acl.waf[0]: Refreshing state... [id=a13139a8-fb10-4545-89fb-924417495223]
module.service.data.aws_iam_policy_document.WafWebAclLoggingDoc[0]: Reading...
module.service.data.aws_iam_policy_document.WafWebAclLoggingDoc[0]: Read complete after 0s [id=919045586]
module.monitoring.aws_cloudwatch_metric_alarm.service_errors: Refreshing state... [id=api-dev-errors]
data.aws_vpc.network: Read complete after 1s [id=vpc-08f522c5cc442d126]
module.monitoring.aws_sns_topic_subscription.email_integration["grantsalerts@navapbc.com"]: Refreshing state... [id=arn:aws:sns:us-east-1:315341936575:api-dev-monitoring:4f5f4bcf-9458-464b-a675-17f6803695dc]
module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy[0]: Refreshing state... [id=service-api-dev-webacl-policy]
module.service.aws_iam_role.migrator_task[0]: Refreshing state... [id=api-dev-migrator]
data.aws_subnets.public: Reading...
data.aws_subnets.private: Reading...
data.aws_subnets.public: Read complete after 0s [id=us-east-1]
module.service.aws_security_group.alb: Refreshing state... [id=sg-025e1dd290c12d572]
module.service.aws_lb_target_group.app_tg[0]: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:targetgroup/app-20240129204404286300000001/2225bef73ea80162]
data.aws_subnets.private: Read complete after 0s [id=us-east-1]
module.service.aws_s3_bucket_public_access_block.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001]
module.service.aws_s3_bucket_lifecycle_configuration.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001]
module.service.data.aws_iam_policy_document.general_purpose_put_access: Reading...
module.service.data.aws_iam_policy_document.general_purpose_put_access: Read complete after 0s [id=612448226]
module.service.aws_s3_bucket_server_side_encryption_configuration.general_purpose_encryption: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001]
module.service.data.aws_ecr_repository.app[0]: Read complete after 1s [id=simpler-grants-gov-api]
module.service.aws_s3_bucket_policy.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001]
module.service.data.aws_iam_policy_document.task_executor: Reading...
module.service.data.aws_iam_policy_document.task_executor: Read complete after 0s [id=3249190051]
module.service.aws_security_group_rule.http_ingress: Refreshing state... [id=sgrule-69662097]
module.service.aws_security_group.app: Refreshing state... [id=sg-0eab49e76a34379f9]
module.service.aws_ecs_task_definition.app: Refreshing state... [id=api-dev]
module.service.aws_iam_role_policy.task_executor: Refreshing state... [id=api-dev-task-executor:api-dev-task-executor-role-policy]
module.service.aws_vpc_security_group_ingress_rule.db_ingress_from_service[0]: Refreshing state... [id=sgr-024fcce0dd2b24824]
aws_sfn_state_machine.copy_oracle_data: Refreshing state... [id=arn:aws:states:us-east-1:315341936575:stateMachine:api-dev-copy-oracle-data]
module.service.aws_s3_bucket_public_access_block.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003]
module.service.aws_s3_bucket_server_side_encryption_configuration.encryption: Refreshing state... [id=api-dev-access-logs20231023213552646900000003]
module.service.data.aws_iam_policy_document.access_logs_put_access: Reading...
module.service.aws_s3_bucket_lifecycle_configuration.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003]
module.service.data.aws_iam_policy_document.access_logs_put_access: Read complete after 0s [id=2049148182]
module.service.aws_s3_bucket_policy.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003]
module.service.aws_ecs_service.app: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:service/api-dev/api-dev]
data.aws_iam_policy.app_db_access_policy[0]: Read complete after 2s [id=arn:aws:iam::315341936575:policy/api-dev-app-access]
module.service.aws_iam_role_policy_attachment.app_service_db_access[0]: Refreshing state... [id=api-dev-app-20231023230412768300000001]
data.aws_iam_policy.migrator_db_access_policy[0]: Read complete after 2s [id=arn:aws:iam::315341936575:policy/api-dev-migrator-access]
module.service.aws_iam_role_policy_attachment.migrator_db_access[0]: Refreshing state... [id=api-dev-migrator-20231023230412789800000002]
module.service.aws_lb.alb[0]: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/api-dev/48f2e65279b967a5]
aws_scheduler_schedule.copy_oracle_data: Refreshing state... [id=api-dev-copy-oracle-data/api-dev-copy-oracle-data]
module.service.aws_lb_listener.alb_listener_http[0]: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:listener/app/api-dev/48f2e65279b967a5/d4ce6505b9614ba0]
module.monitoring.aws_cloudwatch_metric_alarm.high_load_balancer_http_5xx_count: Refreshing state... [id=api-dev-high-load-balancer-5xx-count]
module.monitoring.aws_cloudwatch_metric_alarm.high_app_http_5xx_count: Refreshing state... [id=api-dev-high-app-5xx-count]
module.monitoring.aws_cloudwatch_metric_alarm.high_app_response_time: Refreshing state... [id=api-dev-high-app-response-time]
module.service.aws_lb_listener_rule.app_http_forward[0]: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:listener-rule/app/api-dev/48f2e65279b967a5/d4ce6505b9614ba0/009594b77c825b5a]
module.service.aws_wafv2_web_acl_association.WafWebAclAssociation[0]: Refreshing state... [id=arn:aws:wafv2:us-east-1:315341936575:regional/webacl/api-dev-wafv2-web-acl/a13139a8-fb10-4545-89fb-924417495223,arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/api-dev/48f2e65279b967a5]
module.service.aws_wafv2_web_acl_logging_configuration.WafWebAclLogging[0]: Refreshing state... [id=arn:aws:wafv2:us-east-1:315341936575:regional/webacl/api-dev-wafv2-web-acl/a13139a8-fb10-4545-89fb-924417495223]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_sfn_state_machine.copy_oracle_data will be updated in-place
~ resource "aws_sfn_state_machine" "copy_oracle_data" {
~ definition = jsonencode(
{
- StartAt = "ExecuteECSTask"
- States = {
- ExecuteECSTask = {
- End = true
- Parameters = {
- Cluster = "arn:aws:ecs:us-east-1:315341936575:cluster/api-dev"
- LaunchType = "FARGATE"
- NetworkConfiguration = {
- AwsvpcConfiguration = {
- SecurityGroups = [
- "sg-0eab49e76a34379f9",
]
- Subnets = [
- "subnet-0a5ea667d3751639f",
- "subnet-068ede7dcfd9469ab",
- "subnet-019f469ba97dc6ec7",
]
}
}
- Overrides = {
- ContainerOverrides = [
- {
- Command = [
- "poetry",
- "run",
- "flask",
- "data-migration",
- "copy-oracle-data",
]
- Environment = [
- {
- Name = "FLASK_APP"
- Value = "src.app:create_app()"
},
]
- Name = "api-dev"
},
]
}
- TaskDefinition = "arn:aws:ecs:us-east-1:315341936575:task-definition/api-dev:150"
}
- Resource = "arn:aws:states:::ecs:runTask.sync"
- Type = "Task"
}
}
}
) -> (known after apply)
id = "arn:aws:states:us-east-1:315341936575:stateMachine:api-dev-copy-oracle-data"
name = "api-dev-copy-oracle-data"
tags = {}
# (11 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# module.service.aws_cloudwatch_log_group.WafWebAclLoggroup has moved to module.service.aws_cloudwatch_log_group.WafWebAclLoggroup[0]
resource "aws_cloudwatch_log_group" "WafWebAclLoggroup" {
id = "aws-waf-logs-wafv2-web-acl-api-dev"
name = "aws-waf-logs-wafv2-web-acl-api-dev"
tags = {}
# (7 unchanged attributes hidden)
}
# module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy has moved to module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy[0]
resource "aws_cloudwatch_log_resource_policy" "WafWebAclLoggingPolicy" {
id = "service-api-dev-webacl-policy"
# (2 unchanged attributes hidden)
}
# module.service.aws_ecs_service.app will be updated in-place
~ resource "aws_ecs_service" "app" {
id = "arn:aws:ecs:us-east-1:315341936575:service/api-dev/api-dev"
name = "api-dev"
tags = {}
~ task_definition = "arn:aws:ecs:us-east-1:315341936575:task-definition/api-dev:150" -> (known after apply)
# (15 unchanged attributes hidden)
# (4 unchanged blocks hidden)
}
# module.service.aws_ecs_task_definition.app must be replaced
-/+ resource "aws_ecs_task_definition" "app" {
~ arn = "arn:aws:ecs:us-east-1:315341936575:task-definition/api-dev:150" -> (known after apply)
~ arn_without_revision = "arn:aws:ecs:us-east-1:315341936575:task-definition/api-dev" -> (known after apply)
~ container_definitions = jsonencode(
~ [
~ {
~ linuxParameters = {
~ capabilities = {
- add = []
# (1 unchanged attribute hidden)
}
# (1 unchanged attribute hidden)
}
- mountPoints = []
name = "api-dev"
~ portMappings = [
~ {
- hostPort = 8000
- protocol = "tcp"
# (1 unchanged attribute hidden)
},
]
- systemControls = []
- volumesFrom = []
# (9 unchanged attributes hidden)
},
] # forces replacement
)
~ id = "api-dev" -> (known after apply)
~ revision = 150 -> (known after apply)
- tags = {} -> null
# (11 unchanged attributes hidden)
}
# module.service.aws_lb.alb has moved to module.service.aws_lb.alb[0]
resource "aws_lb" "alb" {
id = "arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/api-dev/48f2e65279b967a5"
name = "api-dev"
tags = {}
# (25 unchanged attributes hidden)
# (5 unchanged blocks hidden)
}
# module.service.aws_lb_listener.alb_listener_http has moved to module.service.aws_lb_listener.alb_listener_http[0]
resource "aws_lb_listener" "alb_listener_http" {
id = "arn:aws:elasticloadbalancing:us-east-1:315341936575:listener/app/api-dev/48f2e65279b967a5/d4ce6505b9614ba0"
tags = {}
# (6 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# module.service.aws_lb_listener_rule.app_http_forward has moved to module.service.aws_lb_listener_rule.app_http_forward[0]
resource "aws_lb_listener_rule" "app_http_forward" {
id = "arn:aws:elasticloadbalancing:us-east-1:315341936575:listener-rule/app/api-dev/48f2e65279b967a5/d4ce6505b9614ba0/009594b77c825b5a"
tags = {}
# (4 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# module.service.aws_lb_target_group.app_tg has moved to module.service.aws_lb_target_group.app_tg[0]
resource "aws_lb_target_group" "app_tg" {
id = "arn:aws:elasticloadbalancing:us-east-1:315341936575:targetgroup/app-20240129204404286300000001/2225bef73ea80162"
name = "app-20240129204404286300000001"
tags = {}
# (18 unchanged attributes hidden)
# (4 unchanged blocks hidden)
}
# module.service.aws_wafv2_web_acl.waf has moved to module.service.aws_wafv2_web_acl.waf[0]
resource "aws_wafv2_web_acl" "waf" {
id = "a13139a8-fb10-4545-89fb-924417495223"
name = "api-dev-wafv2-web-acl"
tags = {}
# (7 unchanged attributes hidden)
# (9 unchanged blocks hidden)
}
# module.service.aws_wafv2_web_acl_association.WafWebAclAssociation has moved to module.service.aws_wafv2_web_acl_association.WafWebAclAssociation[0]
resource "aws_wafv2_web_acl_association" "WafWebAclAssociation" {
id = "arn:aws:wafv2:us-east-1:315341936575:regional/webacl/api-dev-wafv2-web-acl/a13139a8-fb10-4545-89fb-924417495223,arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/api-dev/48f2e65279b967a5"
# (2 unchanged attributes hidden)
}
# module.service.aws_wafv2_web_acl_logging_configuration.WafWebAclLogging has moved to module.service.aws_wafv2_web_acl_logging_configuration.WafWebAclLogging[0]
resource "aws_wafv2_web_acl_logging_configuration" "WafWebAclLogging" {
id = "arn:aws:wafv2:us-east-1:315341936575:regional/webacl/api-dev-wafv2-web-acl/a13139a8-fb10-4545-89fb-924417495223"
# (2 unchanged attributes hidden)
}
Plan: 1 to add, 2 to change, 1 to destroy.
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
```
Summary
Fixes https://github.com/HHS/simpler-grants-gov/issues/1931
Time to review: 4 mins
Changes proposed
modules/task-service
in favor of usingmodules/service
for the analytics package. I originally createdmodules/task-service
as a workaround to avoid needing to do this work, before I realized how easy it would be!enable_load_balancer
to enable the ability to avoid deploying a load balancercount = var.enable_load_balancer ? 1 : 0
to a every load balancer and WAF resourceAmazing Discovery!
In older versions of terraform, adding a
count
to aresource
would force you to do aterraform state mv
or amoved
block to keep the resource intact. Apparently in newer versions of terraform, this is no longer the case!!! It now automatically detects that you have moved a resource. That detection looks like so:Beacuse of this, this PR was MUCH EASIER than I thought it would be! I'm so happy that we are using a recent version of terraform!
terraform plan
inside ofinfra/analytics/service
terraform plan
inside ofinfra/api/service