New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Issue #1553] Deploys a Metabase ECS service #1856
Conversation
# This resource fails to deploy with the following error message: | ||
# | ||
# WAFLogDestinationPermissionIssueException: Unable to deliver logs to the configured destination. | ||
# You might need to grant log delivery permissions for the destination. | ||
# If you're using S3 as your log destination, you might have exceeded your bucket limit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aplybeah have you seen this error before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have, but what triggered it on my end was slightly different from what i'm seeing here. In my case, the waf logs weren't connected to anything, which meant the logs had nowhere to go in the first place. The underlying API call for WAF does create a lot of resources (e.g. its own policy), and I remember reading something about policy character limit being exceeded because of this.
ETA: This may not help, but I resolved this error when I had it by doing a weird order of operations (e.g. apply the log config last)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@/coilysiren Terraform has updated the docs to address this: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration.html
## Summary Partially addresses #1931 Follows up on #1856 ### Time to review: __10 mins__ ## Changes proposed The goal of this PR is to get metabase using the same `modules/service` module the dev API and dev frontend are using. Metabase has a few fundamental settings that need to be changed relative to the dev API, so this PR makes those changes. With those changes made, `modules/metabase-service` can be removed. The changes are: - conditionally add `ecr` pull permissions - conditionally create database access roles (Metabase cannot use IAM to access the database, and therefore does not need these roles) - modifies the load balancer healthcheck path - conditionally removes the container healthcheck, for simplicity - allow pulling an image from a full `image_repository_url` rather than a partial `image_repository_name` - make `readonlyRootFilesystem` a boolean variable, defaults to true - make `linuxParameters` variable, defaults to true ## Context for reviewers This is a complex PR, but ideally it is a no-op from a functional POV. The goal is to get these two services to use the same module, without truly changing anything. On that note, here are the terraform diffs: <details> ``` terraform apply -var="environment_name=dev" -var="image_tag=v0.49.7" module.service.data.aws_region.current: Reading... module.service.aws_cloudwatch_log_group.WafWebAclLoggroup: Refreshing state... [id=aws-waf-logs-wafv2-web-acl-metabase-dev] module.service.aws_ecs_cluster.cluster: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:cluster/metabase-dev] data.aws_vpc.network: Reading... module.service.data.aws_region.current: Read complete after 0s [id=us-east-1] data.aws_rds_cluster.db_cluster: Reading... module.service.aws_cloudwatch_log_group.service_logs: Refreshing state... [id=service/metabase-dev] module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Reading... module.service.data.aws_caller_identity.current: Reading... module.service.aws_s3_bucket.access_logs: Refreshing state... [id=metabase-dev-access-logs20240426185617520000000004] 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=metabase-dev-general-purpose20240426185617519900000003] module.service.aws_iam_role.app_service: Refreshing state... [id=metabase-dev-app] module.service.data.aws_caller_identity.current: Read complete after 0s [id=315341936575] module.service.aws_iam_role.task_executor: Refreshing state... [id=metabase-dev-task-executor] module.service.aws_wafv2_web_acl.waf: Refreshing state... [id=db82e49c-a917-4e30-9a1c-a5f78749bf5a] module.service.data.aws_iam_policy_document.WafWebAclLoggingDoc: Reading... module.service.data.aws_iam_policy_document.WafWebAclLoggingDoc: Read complete after 0s [id=2816859187] module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Refreshing state... [id=analytics-webacl-policy] data.aws_rds_cluster.db_cluster: Read complete after 0s [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=450173802] module.service.aws_iam_role_policy.task_executor: Refreshing state... [id=metabase-dev-task-executor:metabase-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.alb: Refreshing state... [id=sg-0c4edfb171385bc21] module.service.aws_lb_target_group.app_tg: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:targetgroup/app-20240426205400352000000001/debfd3d4006fa28d] 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_security_group_rule.http_ingress: Refreshing state... [id=sgrule-2874082577] module.service.aws_security_group.app: Refreshing state... [id=sg-0f0416c323a602fa8] module.service.aws_s3_bucket_public_access_block.general_purpose: Refreshing state... [id=metabase-dev-general-purpose20240426185617519900000003] module.service.aws_s3_bucket_server_side_encryption_configuration.general_purpose_encryption: Refreshing state... [id=metabase-dev-general-purpose20240426185617519900000003] module.service.aws_s3_bucket_lifecycle_configuration.general_purpose: Refreshing state... [id=metabase-dev-general-purpose20240426185617519900000003] module.service.aws_ecs_task_definition.app: Refreshing state... [id=metabase-dev] 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=3943424410] module.service.aws_s3_bucket_policy.general_purpose: Refreshing state... [id=metabase-dev-general-purpose20240426185617519900000003] module.service.aws_s3_bucket_lifecycle_configuration.access_logs: Refreshing state... [id=metabase-dev-access-logs20240426185617520000000004] module.service.aws_s3_bucket_public_access_block.access_logs: Refreshing state... [id=metabase-dev-access-logs20240426185617520000000004] module.service.aws_s3_bucket_server_side_encryption_configuration.encryption: Refreshing state... [id=metabase-dev-access-logs20240426185617520000000004] module.service.data.aws_iam_policy_document.access_logs_put_access: Reading... module.service.data.aws_iam_policy_document.access_logs_put_access: Read complete after 0s [id=1668394058] module.service.aws_vpc_security_group_ingress_rule.db_ingress_from_service[0]: Refreshing state... [id=sgr-0faef727f6ef997d3] module.service.aws_s3_bucket_policy.access_logs: Refreshing state... [id=metabase-dev-access-logs20240426185617520000000004] module.service.aws_ecs_service.app: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:service/metabase-dev/metabase-dev] module.service.aws_lb.alb: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/metabase-dev/be07ae73a69bf068] module.service.aws_lb_listener.alb_listener_http: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:listener/app/metabase-dev/be07ae73a69bf068/bb6a012d93ffc20b] module.service.aws_lb_listener_rule.app_http_forward: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:listener-rule/app/metabase-dev/be07ae73a69bf068/bb6a012d93ffc20b/e66e8aec66734db2] module.service.aws_wafv2_web_acl_association.WafWebAclAssociation: Refreshing state... [id=arn:aws:wafv2:us-east-1:315341936575:regional/webacl/metabase-dev-wafv2-web-acl/db82e49c-a917-4e30-9a1c-a5f78749bf5a,arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/metabase-dev/be07ae73a69bf068] module.service.aws_wafv2_web_acl_logging_configuration.WafWebAclLogging: Refreshing state... [id=arn:aws:wafv2:us-east-1:315341936575:regional/webacl/metabase-dev-wafv2-web-acl/db82e49c-a917-4e30-9a1c-a5f78749bf5a] 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 Terraform will perform the following actions: # module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy must be replaced -/+ resource "aws_cloudwatch_log_resource_policy" "WafWebAclLoggingPolicy" { ~ id = "analytics-webacl-policy" -> (known after apply) ~ policy_name = "analytics-webacl-policy" -> "service-metabase-dev-webacl-policy" # forces replacement # (1 unchanged attribute 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/metabase-dev/metabase-dev" name = "metabase-dev" tags = {} ~ task_definition = "arn:aws:ecs:us-east-1:315341936575:task-definition/metabase-dev:8" -> (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/metabase-dev:8" -> (known after apply) ~ arn_without_revision = "arn:aws:ecs:us-east-1:315341936575:task-definition/metabase-dev" -> (known after apply) ~ container_definitions = jsonencode( ~ [ ~ { ~ environment = [ + { + 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 = "MB_DB_DBNAME" value = "metabase" }, # (2 unchanged elements hidden) { name = "MB_DB_TYPE" value = "postgres" }, + { + name = "PORT" + value = "3000" }, + { + name = "S3_BUCKET_ARN" + value = "arn:aws:s3:::metabase-dev-general-purpose20240426185617519900000003" }, ] - mountPoints = [] name = "metabase-dev" ~ portMappings = [ ~ { - hostPort = 3000 - protocol = "tcp" # (1 unchanged attribute hidden) }, ] - systemControls = [] - volumesFrom = [] # (7 unchanged attributes hidden) }, ] # forces replacement ) ~ id = "metabase-dev" -> (known after apply) ~ revision = 8 -> (known after apply) - tags = {} -> null # (11 unchanged attributes hidden) } # module.service.aws_iam_role.migrator_task[0] will be created + resource "aws_iam_role" "migrator_task" { + arn = (known after apply) + assume_role_policy = jsonencode( { + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = [ + "states.amazonaws.com", + "scheduler.amazonaws.com", + "ecs-tasks.amazonaws.com", ] } + Sid = "ECSTasksAssumeRole" }, ] + Version = "2012-10-17" } ) + create_date = (known after apply) + force_detach_policies = false + id = (known after apply) + managed_policy_arns = (known after apply) + max_session_duration = 3600 + name = "metabase-dev-migrator" + name_prefix = (known after apply) + path = "/" + 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" } + unique_id = (known after apply) } # module.service.aws_iam_role_policy.task_executor will be updated in-place ~ resource "aws_iam_role_policy" "task_executor" { id = "metabase-dev-task-executor:metabase-dev-task-executor-role-policy" name = "metabase-dev-task-executor-role-policy" ~ policy = jsonencode( ~ { ~ Statement = [ # (6 unchanged elements hidden) { Action = "states:StartExecution" Effect = "Allow" Resource = "arn:aws:states:*:*:stateMachine:*" Sid = "StepFunctionsStartExecution" }, + { + Action = "ecr:GetAuthorizationToken" + Effect = "Allow" + Resource = "*" + Sid = "ECRAuth" }, { Action = "ssm:GetParameters" Effect = "Allow" Resource = [ "arn:aws:ssm:*:*:parameter/metabase/dev/db_user", "arn:aws:ssm:*:*:parameter/metabase/dev/db_pass", ] Sid = "SecretsAccess" }, ] # (1 unchanged attribute hidden) } ) # (2 unchanged attributes hidden) } Plan: 3 to add, 2 to change, 2 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Destroying... [id=analytics-webacl-policy] module.service.aws_ecs_task_definition.app: Destroying... [id=metabase-dev] module.service.aws_iam_role_policy.task_executor: Modifying... [id=metabase-dev-task-executor:metabase-dev-task-executor-role-policy] module.service.aws_iam_role.migrator_task[0]: Creating... module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Destruction complete after 0s module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Creating... module.service.aws_ecs_task_definition.app: Destruction complete after 0s module.service.aws_ecs_task_definition.app: Creating... module.service.aws_iam_role_policy.task_executor: Modifications complete after 0s [id=metabase-dev-task-executor:metabase-dev-task-executor-role-policy] module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Creation complete after 0s [id=service-metabase-dev-webacl-policy] module.service.aws_ecs_task_definition.app: Creation complete after 1s [id=metabase-dev] module.service.aws_ecs_service.app: Modifying... [id=arn:aws:ecs:us-east-1:315341936575:service/metabase-dev/metabase-dev] module.service.aws_iam_role.migrator_task[0]: Creation complete after 1s [id=metabase-dev-migrator] module.service.aws_ecs_service.app: Modifications complete after 1s [id=arn:aws:ecs:us-east-1:315341936575:service/metabase-dev/metabase-dev] Apply complete! Resources: 3 added, 2 changed, 2 destroyed. Outputs: image_tag = "v0.49.7" ``` </details> <details> ``` terraform apply -var="environment_name=dev" data.terraform_remote_state.current_image_tag[0]: Reading... data.aws_iam_policy.migrator_db_access_policy[0]: Reading... module.monitoring.aws_cloudwatch_log_metric_filter.service_error_filter: Refreshing state... [id=service-error-filter] data.aws_vpc.network: Reading... data.aws_rds_cluster.db_cluster[0]: Reading... module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Reading... module.monitoring.aws_sns_topic.this: Refreshing state... [id=arn:aws:sns:us-east-1:315341936575:api-dev-monitoring] module.service.aws_s3_bucket.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001] module.service.data.aws_iam_policy_document.ecs_tasks_assume_role_policy: Read complete after 0s [id=597844978] module.service.aws_s3_bucket.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003] module.service.aws_cloudwatch_log_group.WafWebAclLoggroup: Refreshing state... [id=aws-waf-logs-wafv2-web-acl-api-dev] module.service.aws_wafv2_web_acl.waf: Refreshing state... [id=a13139a8-fb10-4545-89fb-924417495223] module.service.data.aws_caller_identity.current: Reading... module.service.data.aws_caller_identity.current: Read complete after 0s [id=315341936575] module.service.aws_cloudwatch_log_group.service_logs: Refreshing state... [id=service/api-dev] data.aws_iam_policy.app_db_access_policy[0]: Reading... aws_cloudwatch_log_group.copy_oracle_data: Refreshing state... [id=/aws/vendedlogs/states/api-dev-copy-oracle-data20240405180135310900000001] module.service.aws_ecs_cluster.cluster: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:cluster/api-dev] data.aws_rds_cluster.db_cluster[0]: Read complete after 0s [id=api-dev] module.service.data.aws_region.current: Reading... module.service.data.aws_region.current: Read complete after 0s [id=us-east-1] module.service.data.aws_ecr_repository.app[0]: Reading... aws_scheduler_schedule_group.copy_oracle_data: Refreshing state... [id=api-dev-copy-oracle-data] data.terraform_remote_state.current_image_tag[0]: Read complete after 1s module.service.aws_iam_role.task_executor: Refreshing state... [id=api-dev-task-executor] data.aws_vpc.network: Read complete after 0s [id=vpc-08f522c5cc442d126] module.service.aws_iam_role.app_service: Refreshing state... [id=api-dev-app] module.monitoring.aws_cloudwatch_metric_alarm.service_errors: Refreshing state... [id=api-dev-errors] 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.data.aws_iam_policy_document.WafWebAclLoggingDoc: Reading... module.service.data.aws_iam_policy_document.WafWebAclLoggingDoc: Read complete after 0s [id=919045586] data.aws_subnets.private: Reading... data.aws_subnets.public: Reading... module.service.aws_lb_target_group.app_tg: 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_security_group.alb: Refreshing state... [id=sg-025e1dd290c12d572] data.aws_subnets.public: Read complete after 0s [id=us-east-1] 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_public_access_block.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003] module.service.aws_s3_bucket_policy.access_logs: Refreshing state... [id=api-dev-access-logs20231023213552646900000003] module.service.aws_s3_bucket_lifecycle_configuration.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001] module.service.aws_s3_bucket_server_side_encryption_configuration.general_purpose_encryption: 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_public_access_block.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001] 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_s3_bucket_policy.general_purpose: Refreshing state... [id=api-dev-general-purpose20240416221336163000000001] module.service.aws_lb.alb: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:315341936575:loadbalancer/app/api-dev/48f2e65279b967a5] module.service.aws_lb_listener.alb_listener_http: 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_response_time: Refreshing state... [id=api-dev-high-app-response-time] module.monitoring.aws_cloudwatch_metric_alarm.high_app_http_5xx_count: Refreshing state... [id=api-dev-high-app-5xx-count] data.aws_iam_policy.migrator_db_access_policy[0]: Read complete after 2s [id=arn:aws:iam::315341936575:policy/api-dev-migrator-access] 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.migrator_task[0]: Refreshing state... [id=api-dev-migrator] module.service.aws_vpc_security_group_ingress_rule.db_ingress_from_service[0]: Refreshing state... [id=sgr-024fcce0dd2b24824] module.service.data.aws_ecr_repository.app[0]: Read complete after 2s [id=simpler-grants-gov-api] module.service.aws_iam_role_policy_attachment.app_service_db_access[0]: Refreshing state... [id=api-dev-app-20231023230412768300000001] 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_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] 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_ecs_service.app: Refreshing state... [id=arn:aws:ecs:us-east-1:315341936575:service/api-dev/api-dev] module.service.aws_iam_role_policy_attachment.migrator_db_access[0]: Refreshing state... [id=api-dev-migrator-20231023230412789800000002] module.service.aws_lb_listener_rule.app_http_forward: 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: 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: Refreshing state... [id=arn:aws:wafv2:us-east-1:315341936575:regional/webacl/api-dev-wafv2-web-acl/a13139a8-fb10-4545-89fb-924417495223] aws_scheduler_schedule.copy_oracle_data: Refreshing state... [id=api-dev-copy-oracle-data/api-dev-copy-oracle-data] 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 Terraform will perform the following actions: # aws_scheduler_schedule.copy_oracle_data will be updated in-place ~ resource "aws_scheduler_schedule" "copy_oracle_data" { id = "api-dev-copy-oracle-data/api-dev-copy-oracle-data" name = "api-dev-copy-oracle-data" ~ state = "DISABLED" -> "ENABLED" # (9 unchanged attributes hidden) # (2 unchanged blocks hidden) } # 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:148" } - 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_resource_policy.WafWebAclLoggingPolicy will be created + resource "aws_cloudwatch_log_resource_policy" "WafWebAclLoggingPolicy" { + id = (known after apply) + policy_document = jsonencode( { + Statement = [ + { + Action = [ + "logs:PutLogEvents", + "logs:CreateLogStream", ] + Condition = { + ArnLike = { + "aws:SourceArn" = "arn:aws:logs:us-east-1:315341936575:*" } + StringEquals = { + "aws:SourceAccount" = "315341936575" } } + Effect = "Allow" + Principal = { + Service = "delivery.logs.amazonaws.com" } + Resource = "arn:aws:logs:us-east-1:315341936575:log-group:aws-waf-logs-wafv2-web-acl-api-dev:*" }, ] + Version = "2012-10-17" } ) + policy_name = "service-api-dev-webacl-policy" } # 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:148" -> (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:148" -> (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 = 148 -> (known after apply) - tags = {} -> null # (11 unchanged attributes hidden) } Plan: 2 to add, 3 to change, 1 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.service.aws_ecs_task_definition.app: Destroying... [id=api-dev] module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Creating... module.service.aws_ecs_task_definition.app: Destruction complete after 1s module.service.aws_ecs_task_definition.app: Creating... module.service.aws_cloudwatch_log_resource_policy.WafWebAclLoggingPolicy: Creation complete after 1s [id=service-api-dev-webacl-policy] module.service.aws_ecs_task_definition.app: Creation complete after 0s [id=api-dev] aws_sfn_state_machine.copy_oracle_data: Modifying... [id=arn:aws:states:us-east-1:315341936575:stateMachine:api-dev-copy-oracle-data] module.service.aws_ecs_service.app: Modifying... [id=arn:aws:ecs:us-east-1:315341936575:service/api-dev/api-dev] module.service.aws_ecs_service.app: Modifications complete after 1s [id=arn:aws:ecs:us-east-1:315341936575:service/api-dev/api-dev] aws_sfn_state_machine.copy_oracle_data: Modifications complete after 1s [id=arn:aws:states:us-east-1:315341936575:stateMachine:api-dev-copy-oracle-data] aws_scheduler_schedule.copy_oracle_data: Modifying... [id=api-dev-copy-oracle-data/api-dev-copy-oracle-data] aws_scheduler_schedule.copy_oracle_data: Modifications complete after 1s [id=api-dev-copy-oracle-data/api-dev-copy-oracle-data] Apply complete! Resources: 2 added, 3 changed, 1 destroyed. Outputs: application_log_group = "service/api-dev" application_log_stream_prefix = "api-dev" image_tag = "25f818723bcdf215ef7da94e392b1b8fba34e3ff" migrator_role_arn = "arn:aws:iam::315341936575:role/api-dev-migrator" service_cluster_name = "api-dev" service_endpoint = "http://api-dev-1839587515.us-east-1.elb.amazonaws.com" service_name = "api-dev" ``` </details>
Summary
Fixes #1553
Time to review: 10 mins, yes I know its 1200 lines! Try to skim it.
PR structure
The bulk of this code was copied from
infra/analytics/service
andinfra/modules/service
. That's why this PR is so large, it was a copy then modify operation. Some notable aspects are:MB_DB_
environment variables and secret configinfra/modules/metabase-service
is the same asinfra/modules/service
Context for reviewers
If you want to review something, it might be easiest to review the commits. I didn't specifically write the commits to be reviewable, but they exist!
Testing
http://metabase-dev-710651776.us-east-1.elb.amazonaws.com/