Skip to content
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

feat(notes): basic infrastructure and server setup for notes #968

Merged
merged 8 commits into from
Nov 20, 2024

Conversation

kschelonka
Copy link
Contributor

@kschelonka kschelonka commented Nov 20, 2024

Set up basic infrastructure for notes with:

  • Postgres serverless aurora DB
  • Apollo server + minimal schema
  • GH Actions deployment
  • Local DB setup scripts
  • Account deletion topic subscription and queue commented out because there's no data yet

Non-Code steps:

  • Create Sentry project and add DSN to parameter store
  • Deploy to dev (need to figure this out selectively)

@kschelonka kschelonka requested a review from a team as a code owner November 20, 2024 00:47
@kschelonka kschelonka requested review from bassrock and removed request for a team November 20, 2024 00:47
Copy link

github-actions bot commented Nov 20, 2024

Plan Result (braze-cdk-production)

CI link

Plan: 0 to add, 1 to change, 0 to destroy.
  • Update
    • aws_route53_record.newsletter_email_1_text_records_CAF8FF32
Change Result (Click me)
  # aws_route53_record.newsletter_email_1_text_records_CAF8FF32 will be updated in-place
  ~ resource "aws_route53_record" "newsletter_email_1_text_records_CAF8FF32" {
        id                               = "Z21HMDYFB951W4_today_TXT"
        name                             = "today"
      ~ records                          = [
          - "v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; fo=1; sp=none; aspf=r;",
            # (2 unchanged elements hidden)
        ]
        # (7 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Copy link

github-actions bot commented Nov 20, 2024

Plan Result (pocket-event-bridge-cdk-production)

CI link

Plan: 0 to add, 6 to change, 0 to destroy.
  • Update
    • aws_cloudwatch_event_rule.collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_83F8780B
    • aws_cloudwatch_event_target.collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_event-bridge-target-PocketEventBridge-Prod-Collection-Event-SNS-Target_3B1D895E
    • aws_cloudwatch_metric_alarm.corpus-events-topic_corpusevents-rule-dlq-alarm_AD6CFB1B
    • aws_cloudwatch_metric_alarm.shareable-list-events-topic_shareablelistevents-rule-dlq-alarm_CE6C49ED
    • aws_cloudwatch_metric_alarm.shareable-list-item-events-topic_shareablelistitemevents-rule-dlq-alarm_3210A864
    • aws_cloudwatch_metric_alarm.user-events-topic_userevents-rule-dlq-alarm_B2A4F488
Change Result (Click me)
  # aws_cloudwatch_event_rule.collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_83F8780B will be updated in-place
  ~ resource "aws_cloudwatch_event_rule" "collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_83F8780B" {
      ~ event_pattern       = jsonencode(
          ~ {
              ~ detail-type = [
                  - "collection-created",
                    "collection-updated",
                  + "collection-created",
                ]
                # (1 unchanged attribute hidden)
            }
        )
        id                  = "PocketEventBridge-Prod-Shared-Event-Bus/PocketEventBridge-Prod-CollectionEvents-Rule-Rule"
        name                = "PocketEventBridge-Prod-CollectionEvents-Rule-Rule"
        tags                = {}
        # (10 unchanged attributes hidden)
    }

  # aws_cloudwatch_event_target.collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_event-bridge-target-PocketEventBridge-Prod-Collection-Event-SNS-Target_3B1D895E will be updated in-place
  ~ resource "aws_cloudwatch_event_target" "collection-events-topic_PocketEventBridge-Prod-CollectionEvents-EventBridge-Rule_event-bridge-rule_event-bridge-target-PocketEventBridge-Prod-Collection-Event-SNS-Target_3B1D895E" {
      ~ arn            = "arn:aws:sns:us-east-1:996905175585:PocketEventBridge-Prod-CollectionEventTopic" -> "arn:aws:sns:us-east-1:996905175585:PocketEventBridge-Prod-CollectionEvents"
        id             = "PocketEventBridge-Prod-Shared-Event-Bus-PocketEventBridge-Prod-CollectionEvents-Rule-Rule-PocketEventBridge-Prod-Collection-Event-SNS-Target"
        # (7 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

  # aws_cloudwatch_metric_alarm.corpus-events-topic_corpusevents-rule-dlq-alarm_AD6CFB1B will be updated in-place
  ~ resource "aws_cloudwatch_metric_alarm" "corpus-events-topic_corpusevents-rule-dlq-alarm_AD6CFB1B" {
      ~ dimensions                            = {
          ~ "QueueName" = "PocketEventBridge-Prod-SNS-CorpusEvents-Topic-DLQ" -> "PocketEventBridge-Prod-SNS-CorpusEvents-Event-Rule-DLQ"
        }
        id                                    = "PocketEventBridge-Prod-CorpusEvents-Rule-dlq-alarm"
        tags                                  = {}
        # (21 unchanged attributes hidden)
    }

  # aws_cloudwatch_metric_alarm.shareable-list-events-topic_shareablelistevents-rule-dlq-alarm_CE6C49ED will be updated in-place
  ~ resource "aws_cloudwatch_metric_alarm" "shareable-list-events-topic_shareablelistevents-rule-dlq-alarm_CE6C49ED" {
      ~ dimensions                            = {
          ~ "QueueName" = "PocketEventBridge-Prod-SNS-ShareableListEvents-Topic-DLQ" -> "PocketEventBridge-Prod-SNS-ShareableListEvents-Event-Rule-DLQ"
        }
        id                                    = "PocketEventBridge-Prod-ShareableListEvents-Rule-dlq-alarm"
        tags                                  = {}
        # (21 unchanged attributes hidden)
    }

  # aws_cloudwatch_metric_alarm.shareable-list-item-events-topic_shareablelistitemevents-rule-dlq-alarm_3210A864 will be updated in-place
  ~ resource "aws_cloudwatch_metric_alarm" "shareable-list-item-events-topic_shareablelistitemevents-rule-dlq-alarm_3210A864" {
      ~ dimensions                            = {
          ~ "QueueName" = "PocketEventBridge-Prod-SNS-ShareableListItemEvents-Topic-DLQ" -> "PocketEventBridge-Prod-SNS-ShareableListItemEvents-Event-Rule-DLQ"
        }
        id                                    = "PocketEventBridge-Prod-ShareableListItemEvents-Rule-dlq-alarm"
        tags                                  = {}
        # (21 unchanged attributes hidden)
    }

  # aws_cloudwatch_metric_alarm.user-events-topic_userevents-rule-dlq-alarm_B2A4F488 will be updated in-place
  ~ resource "aws_cloudwatch_metric_alarm" "user-events-topic_userevents-rule-dlq-alarm_B2A4F488" {
      ~ dimensions                            = {
          ~ "QueueName" = "PocketEventBridge-Prod-UserEvents-Topic-Rule-DLQ" -> "PocketEventBridge-Prod-SNS-UserEvents-Event-Rule-DLQ"
        }
        id                                    = "PocketEventBridge-Prod-UserEvents-Rule-dlq-alarm"
        tags                                  = {}
        # (21 unchanged attributes hidden)
    }

Plan: 0 to add, 6 to change, 0 to destroy.

Copy link

github-actions bot commented Nov 20, 2024

Plan Result (notes-api-cdk-production)

CI link

Plan: 54 to add, 0 to change, 0 to destroy.
  • Create
    • aws_acm_certificate.application_alb_certificate_93966247
    • aws_acm_certificate_validation.application_alb_certificate_certificate_validation_25DAB195
    • aws_alb.application_application_load_balancer_alb_05EA9801
    • aws_alb_listener.application_listener_http_D74EC0ED
    • aws_alb_listener.application_listener_https_D31CB055
    • aws_alb_listener_rule.application_ecs_service_listener_rule_903F815F
    • aws_alb_target_group.application_ecs_service_blue_target_group_ecs_target_group_4A9BF49B
    • aws_alb_target_group.application_ecs_service_green_target_group_ecs_target_group_4E06DCA6
    • aws_appautoscaling_policy.application_autoscaling_scale_in_policy_BF273511
    • aws_appautoscaling_policy.application_autoscaling_scale_out_policy_D03900A2
    • aws_appautoscaling_target.application_autoscaling_autoscaling_target_42BF5C99
    • aws_cloudwatch_dashboard.application_cloudwatch-dashboard_1F3DC0ED
    • aws_cloudwatch_log_group.app-log-group
    • aws_cloudwatch_metric_alarm.application_alarm-httptarget5xxerrorrate_F94D87C0
    • aws_cloudwatch_metric_alarm.application_autoscaling_scale_in_alarm_850BE3A1
    • aws_cloudwatch_metric_alarm.application_autoscaling_scale_out_alarm_E40FCBA0
    • aws_cloudwatch_metric_alarm.synthetics_synthetics_synthetic_check_alarm_query_0_52F9FF21
    • aws_cloudwatch_metric_alarm.synthetics_synthetics_synthetic_check_alarm_uptime_0_3A56DFC7
    • aws_codedeploy_app.application_ecs_service_ecs_codedeploy_ecs_code_deploy_C2F7CBCF
    • aws_codedeploy_deployment_group.application_ecs_service_ecs_codedeploy_ecs_codedeploy_deployment_group_48384247
    • aws_codestarnotifications_notification_rule.application_ecs_service_ecs_codedeploy_ecs_codedeploy_notifications_CB44EADE
    • aws_db_subnet_group.rds_rds_subnet_group_796D20B7
    • aws_ecr_lifecycle_policy.application_ecs_service_ecr-app_ecr-repo-lifecyclepolicy_CCDF75B7
    • aws_ecr_repository.application_ecs_service_ecr-app_ecr-repo_ABFE17F0
    • aws_ecs_cluster.application_ecs_cluster_4DC6EFB3
    • aws_ecs_service.application_ecs_service_ecs-service_A8BAB5F4
    • aws_ecs_task_definition.application_ecs_service_ecs-task_461CC9D4
    • aws_iam_policy.application_ecs_service_ecs-iam_ecs-task-execution-role-policy_2D469A77
    • aws_iam_policy.application_ecs_service_ecs-iam_ecs-task-role-policy_6FC89FB6
    • aws_iam_policy.synthetics_synthetics_synthetic_check_access_policy_9A7D8849
    • aws_iam_role.application_ecs_service_ecs-iam_ecs-execution-role_FB754BAA
    • aws_iam_role.application_ecs_service_ecs-iam_ecs-task-role_A72990ED
    • aws_iam_role.application_ecs_service_ecs_codedeploy_ecs_code_deploy_role_175DB7D3
    • aws_iam_role.synthetics_synthetic_check_role_A3A5C38B
    • aws_iam_role_policy_attachment.application_ecs_service_ecs-iam_ecs-task-custom-attachment_F8DDD355
    • aws_iam_role_policy_attachment.application_ecs_service_ecs-iam_ecs-task-execution-custom-attachment_046B7E2E
    • aws_iam_role_policy_attachment.application_ecs_service_ecs-iam_ecs-task-execution-default-attachment_99A621FF
    • aws_iam_role_policy_attachment.application_ecs_service_ecs_codedeploy_ecs_codedeploy_role_attachment_1A1D5725
    • aws_iam_role_policy_attachment.synthetics_synthetics_synthetic_check_access_attach_BC7F9559
    • aws_rds_cluster.rds_rds_cluster_1A0399FD
    • aws_rds_cluster_instance.rds_rds-instance_6675FA88
    • aws_route53_record.application_alb_certificate_certificate_record_51B45CF2
    • aws_route53_record.application_alb_record_8EA9D3F9
    • aws_route53_record.application_base_dns_subhosted_zone_ns_DFB88A22
    • aws_route53_zone.application_base_dns_subhosted_zone_77521D1C
    • aws_s3_bucket.synthetics_synthetics_synthetic_check_artifacts_53DD59E6
    • aws_s3_bucket_lifecycle_configuration.synthetics_synthetics_synthetic_check_artifacts_lifecycle_5A7B9150
    • aws_secretsmanager_secret.rds_rds_secret_A0401B27
    • aws_secretsmanager_secret_version.rds_rds_secret_version_11D8C2B1
    • aws_security_group.application_application_load_balancer_alb_security_group_7B45D070
    • aws_security_group.application_ecs_service_ecs_security_group_231C6B1E
    • aws_security_group.rds_rds_security_group_B7738CEB
    • aws_synthetics_canary.synthetics_synthetics_synthetic_check_query_0_99E4AE1B
    • aws_synthetics_canary.synthetics_synthetics_synthetic_check_uptime_0_4168D0DB
Change Result (Click me)

⚠️ The content is omitted as it is too long. ⚠️

  # data.aws_iam_policy_document.synthetics_synthetics_synthetic_check_access_4C83FECF will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "synthetics_synthetics_synthetic_check_access_4C83FECF" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)
      + version       = "2012-10-17"

      + statement {
          + actions   = [
              + "logs:CreateLogGroup",
              + "logs:CreateLogStream",
              + "logs:PutLogEvents",
            ]
          + effect    = "Allow"
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "s3:GetObject",
              + "s3:PutObject",
            ]
          + resources = [
              + (known after apply),
            ]
        }
      + statement {
          + actions   = [
              + "s3:GetObject",
            ]
          + resources = [
              + "arn:aws:s3:::pocket-syntheticchecks-prod/*",
            ]
        }
      + statement {
          + actions   = [
              + "s3:GetBucketLocation",
            ]
          + resources = [
              + (known after apply),
            ]
        }
      + statement {
          + actions   = [
              + "s3:ListAllMyBuckets",
            ]
          + resources = [
              + "*",
            ]
        }
      + statement {
          + actions   = [
              + "cloudwatch:PutMetricData",
            ]
          + resources = [
              + "*",
            ]

          + condition {
              + test     = "StringEquals"
              + values   = [
                  + "CloudWatchSynthetics",
                ]
              + variable = "cloudwatch:namespace"
            }
        }
      + statement {
          + actions   = [
              + "ec2:AttachNetworkInterface",
              + "ec2:CreateNetworkInterface",
              + "ec2:DeleteNetworkInterface",
              + "ec2:DescribeNetworkInterfaces",
            ]
          + resources = [
              + "*",
            ]
        }
    }

  # aws_acm_certificate.application_alb_certificate_93966247 will be created
  + resource "aws_acm_certificate" "application_alb_certificate_93966247" {
      + arn                       = (known after apply)
      + domain_name               = "notes.readitlater.com"
      + domain_validation_options = [
          + {
              + domain_name           = "notes.readitlater.com"
              + resource_record_name  = (known after apply)
              + resource_record_type  = (known after apply)
              + resource_record_value = (known after apply)
            },
        ]
      + id                        = (known after apply)
      + key_algorithm             = (known after apply)
      + not_after                 = (known after apply)
      + not_before                = (known after apply)
      + pending_renewal           = (known after apply)
      + renewal_eligibility       = (known after apply)
      + renewal_summary           = (known after apply)
      + status                    = (known after apply)
      + subject_alternative_names = [
          + "notes.readitlater.com",
        ]
      + tags                      = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all                  = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + type                      = (known after apply)
      + validation_emails         = (known after apply)
      + validation_method         = "DNS"
    }

  # aws_acm_certificate_validation.application_alb_certificate_certificate_validation_25DAB195 will be created
  + resource "aws_acm_certificate_validation" "application_alb_certificate_certificate_validation_25DAB195" {
      + certificate_arn         = (known after apply)
      + id                      = (known after apply)
      + validation_record_fqdns = (known after apply)
    }

  # aws_alb.application_application_load_balancer_alb_05EA9801 will be created
  + resource "aws_alb" "application_application_load_balancer_alb_05EA9801" {
      + arn                                                          = (known after apply)
      + arn_suffix                                                   = (known after apply)
      + client_keep_alive                                            = 3600
      + desync_mitigation_mode                                       = "defensive"
      + dns_name                                                     = (known after apply)
      + drop_invalid_header_fields                                   = false
      + enable_deletion_protection                                   = false
      + enable_http2                                                 = true
      + enable_tls_version_and_cipher_suite_headers                  = false
      + enable_waf_fail_open                                         = false
      + enable_xff_client_port                                       = false
      + enforce_security_group_inbound_rules_on_private_link_traffic = (known after apply)
      + id                                                           = (known after apply)
      + idle_timeout                                                 = 60
      + internal                                                     = true
      + ip_address_type                                              = (known after apply)
      + load_balancer_type                                           = "application"
      + name                                                         = (known after apply)
      + name_prefix                                                  = "NOTES"
      + preserve_host_header                                         = false
      + security_groups                                              = (known after apply)
      + subnets                                                      = [
          + "subnet-610bdb3b",
          + "subnet-b2a036fa",
          + "subnet-cc66bde0",
          + "subnet-d09eb8ec",
        ]
      + tags                                                         = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all                                                     = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + vpc_id                                                       = (known after apply)
      + xff_header_processing_mode                                   = "append"
      + zone_id                                                      = (known after apply)

      + access_logs {
          + bucket  = "pocket-data-items"
          + enabled = true
          + prefix  = "server-logs/notesapi-prod/alb"
        }
    }

  # aws_alb_listener.application_listener_http_D74EC0ED will be created
  + resource "aws_alb_listener" "application_listener_http_D74EC0ED" {
      + arn                      = (known after apply)
      + id                       = (known after apply)
      + load_balancer_arn        = (known after apply)
      + port                     = 80
      + protocol                 = "HTTP"
      + ssl_policy               = (known after apply)
      + tags                     = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all                 = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tcp_idle_timeout_seconds = (known after apply)

      + default_action {
          + order = (known after apply)
          + type  = "redirect"

          + redirect {
              + host        = "#{host}"
              + path        = "/#{path}"
              + port        = "443"
              + protocol    = "HTTPS"
              + query       = "#{query}"
              + status_code = "HTTP_301"
            }
        }
    }

  # aws_alb_listener.application_listener_https_D31CB055 will be created
  + resource "aws_alb_listener" "application_listener_https_D31CB055" {
      + arn                      = (known after apply)
      + certificate_arn          = (known after apply)
      + id                       = (known after apply)
      + load_balancer_arn        = (known after apply)
      + port                     = 443
      + protocol                 = "HTTPS"
      + ssl_policy               = "ELBSecurityPolicy-TLS-1-1-2017-01"
      + tags                     = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all                 = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tcp_idle_timeout_seconds = (known after apply)

      + default_action {
          + order = (known after apply)
          + type  = "fixed-response"

          + fixed_response {
              + content_type = "text/plain"
              + status_code  = "503"
                # (1 unchanged attribute hidden)
            }
        }
    }

  # aws_alb_listener_rule.application_ecs_service_listener_rule_903F815F will be created
  + resource "aws_alb_listener_rule" "application_ecs_service_listener_rule_903F815F" {
      + arn          = (known after apply)
      + id           = (known after apply)
      + listener_arn = (known after apply)
      + priority     = 1
      + tags         = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all     = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }

      + action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }

      + condition {
          + path_pattern {
              + values = [
                  + "*",
                ]
            }
        }
    }

  # aws_alb_target_group.application_ecs_service_blue_target_group_ecs_target_group_4A9BF49B will be created
  + resource "aws_alb_target_group" "application_ecs_service_blue_target_group_ecs_target_group_4A9BF49B" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = (known after apply)
      + deregistration_delay               = "120"
      + id                                 = (known after apply)
      + ip_address_type                    = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + load_balancer_arns                 = (known after apply)
      + load_balancing_algorithm_type      = (known after apply)
      + load_balancing_anomaly_mitigation  = (known after apply)
      + load_balancing_cross_zone_enabled  = (known after apply)
      + name                               = (known after apply)
      + name_prefix                        = "NOTESb"
      + port                               = 80
      + preserve_client_ip                 = (known after apply)
      + protocol                           = "HTTP"
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + tags                               = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
          + "type"           = "blue"
        }
      + tags_all                           = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
          + "type"           = "blue"
        }
      + target_type                        = "ip"
      + vpc_id                             = "vpc-867638e3"

      + health_check {
          + enabled             = true
          + healthy_threshold   = 5
          + interval            = 15
          + matcher             = (known after apply)
          + path                = "/.well-known/apollo/server-health"
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = (known after apply)
          + unhealthy_threshold = 3
        }
    }

  # aws_alb_target_group.application_ecs_service_green_target_group_ecs_target_group_4E06DCA6 will be created
  + resource "aws_alb_target_group" "application_ecs_service_green_target_group_ecs_target_group_4E06DCA6" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = (known after apply)
      + deregistration_delay               = "120"
      + id                                 = (known after apply)
      + ip_address_type                    = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + load_balancer_arns                 = (known after apply)
      + load_balancing_algorithm_type      = (known after apply)
      + load_balancing_anomaly_mitigation  = (known after apply)
      + load_balancing_cross_zone_enabled  = (known after apply)
      + name                               = (known after apply)
      + name_prefix                        = "NOTESg"
      + port                               = 80
      + preserve_client_ip                 = (known after apply)
      + protocol                           = "HTTP"
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + tags                               = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
          + "type"           = "green"
        }
      + tags_all                           = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
          + "type"           = "green"
        }
      + target_type                        = "ip"
      + vpc_id                             = "vpc-867638e3"

      + health_check {
          + enabled             = true
          + healthy_threshold   = 5
          + interval            = 15
          + matcher             = (known after apply)
          + path                = "/.well-known/apollo/server-health"
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = (known after apply)
          + unhealthy_threshold = 3
        }
    }

  # aws_appautoscaling_policy.application_autoscaling_scale_in_policy_BF273511 will be created
  + resource "aws_appautoscaling_policy" "application_autoscaling_scale_in_policy_BF273511" {
      + alarm_arns         = (known after apply)
      + arn                = (known after apply)
      + id                 = (known after apply)
      + name               = "NotesAPI-Prod-ScaleInPolicy"
      + policy_type        = "StepScaling"
      + resource_id        = "service/NotesAPI-Prod/NotesAPI-Prod"
      + scalable_dimension = "ecs:service:DesiredCount"
      + service_namespace  = "ecs"

      + step_scaling_policy_configuration {
          + adjustment_type         = "ChangeInCapacity"
          + cooldown                = 60
          + metric_aggregation_type = "Average"

          + step_adjustment {
              + metric_interval_upper_bound = "0"
              + scaling_adjustment          = -1
                # (1 unchanged attribute hidden)
            }
        }
    }

  # aws_appautoscaling_policy.application_autoscaling_scale_out_policy_D03900A2 will be created
  + resource "aws_appautoscaling_policy" "application_autoscaling_scale_out_policy_D03900A2" {
      + alarm_arns         = (known after apply)
      + arn                = (known after apply)
      + id                 = (known after apply)
      + name               = "NotesAPI-Prod-ScaleOutPolicy"
      + policy_type        = "StepScaling"
      + resource_id        = "service/NotesAPI-Prod/NotesAPI-Prod"
      + scalable_dimension = "ecs:service:DesiredCount"
      + service_namespace  = "ecs"

      + step_scaling_policy_configuration {
          + adjustment_type         = "ChangeInCapacity"
          + cooldown                = 60
          + metric_aggregation_type = "Average"

          + step_adjustment {
              + metric_interval_lower_bound = "0"
              + scaling_adjustment          = 2
                # (1 unchanged attribute hidden)
            }
        }
    }

  # aws_appautoscaling_target.application_autoscaling_autoscaling_target_42BF5C99 will be created
  + resource "aws_appautoscaling_target" "application_autoscaling_autoscaling_target_42BF5C99" {
      + arn                = (known after apply)
      + id                 = (known after apply)
      + max_capacity       = 10
      + min_capacity       = 2
      + resource_id        = "service/NotesAPI-Prod/NotesAPI-Prod"
      + role_arn      

# ...
# ... The maximum length of GitHub Comment is 65536, so the content is omitted by tfcmt.
# ...

ter apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = (known after apply)
      + preferred_backup_window               = (known after apply)
      + preferred_maintenance_window          = (known after apply)
      + promotion_tier                        = 0
      + publicly_accessible                   = (known after apply)
      + storage_encrypted                     = (known after apply)
      + tags_all                              = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + writer                                = (known after apply)
    }

  # aws_route53_record.application_alb_certificate_certificate_record_51B45CF2 will be created
  + resource "aws_route53_record" "application_alb_certificate_certificate_record_51B45CF2" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = (known after apply)
      + records         = (known after apply)
      + ttl             = 60
      + type            = (known after apply)
      + zone_id         = (known after apply)
    }

  # aws_route53_record.application_alb_record_8EA9D3F9 will be created
  + resource "aws_route53_record" "application_alb_record_8EA9D3F9" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "notes.readitlater.com"
      + set_identifier  = "1"
      + type            = "A"
      + zone_id         = (known after apply)

      + alias {
          + evaluate_target_health = true
          + name                   = (known after apply)
          + zone_id                = (known after apply)
        }

      + weighted_routing_policy {
          + weight = 1
        }
    }

  # aws_route53_record.application_base_dns_subhosted_zone_ns_DFB88A22 will be created
  + resource "aws_route53_record" "application_base_dns_subhosted_zone_ns_DFB88A22" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "notes.readitlater.com"
      + records         = (known after apply)
      + ttl             = 86400
      + type            = "NS"
      + zone_id         = "Z2BHWTOWFVNW3M"
    }

  # aws_route53_zone.application_base_dns_subhosted_zone_77521D1C will be created
  + resource "aws_route53_zone" "application_base_dns_subhosted_zone_77521D1C" {
      + arn                 = (known after apply)
      + comment             = "Managed by Terraform"
      + force_destroy       = false
      + id                  = (known after apply)
      + name                = "notes.readitlater.com"
      + name_servers        = (known after apply)
      + primary_name_server = (known after apply)
      + tags                = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all            = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + zone_id             = (known after apply)
    }

  # aws_s3_bucket.synthetics_synthetics_synthetic_check_artifacts_53DD59E6 will be created
  + resource "aws_s3_bucket" "synthetics_synthetics_synthetic_check_artifacts_53DD59E6" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "pocket-notesapi-prod-synthetic-checks"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + 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                    = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)
    }

  # aws_s3_bucket_lifecycle_configuration.synthetics_synthetics_synthetic_check_artifacts_lifecycle_5A7B9150 will be created
  + resource "aws_s3_bucket_lifecycle_configuration" "synthetics_synthetics_synthetic_check_artifacts_lifecycle_5A7B9150" {
      + bucket                                 = (known after apply)
      + id                                     = (known after apply)
      + transition_default_minimum_object_size = (known after apply)

      + rule {
          + id     = "30-day-retention"
          + status = "Enabled"

          + expiration {
              + days                         = 30
              + expired_object_delete_marker = (known after apply)
            }
        }
    }

  # aws_secretsmanager_secret.rds_rds_secret_A0401B27 will be created
  + resource "aws_secretsmanager_secret" "rds_rds_secret_A0401B27" {
      + arn                            = (known after apply)
      + description                    = (known after apply)
      + force_overwrite_replica_secret = false
      + id                             = (known after apply)
      + name                           = (known after apply)
      + name_prefix                    = (known after apply)
      + policy                         = (known after apply)
      + recovery_window_in_days        = 30
      + tags                           = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all                       = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
    }

  # aws_secretsmanager_secret_version.rds_rds_secret_version_11D8C2B1 will be created
  + resource "aws_secretsmanager_secret_version" "rds_rds_secret_version_11D8C2B1" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + secret_id      = (known after apply)
      + secret_string  = (sensitive value)
      + version_id     = (known after apply)
      + version_stages = (known after apply)
    }

  # aws_security_group.application_application_load_balancer_alb_security_group_7B45D070 will be created
  + resource "aws_security_group" "application_application_load_balancer_alb_security_group_7B45D070" {
      + arn                    = (known after apply)
      + description            = "External security group  (Managed by Terraform)"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "required"
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + from_port        = 443
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 443
                # (1 unchanged attribute hidden)
            },
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + from_port        = 80
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 80
                # (1 unchanged attribute hidden)
            },
        ]
      + name                   = (known after apply)
      + name_prefix            = "NotesAPI-Prod-HTTP/S Security Group"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Name"           = "NotesAPI-Prod-HTTP/S Security Group"
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all               = {
          + "Name"           = "NotesAPI-Prod-HTTP/S Security Group"
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + vpc_id                 = "vpc-867638e3"
    }

  # aws_security_group.application_ecs_service_ecs_security_group_231C6B1E will be created
  + resource "aws_security_group" "application_ecs_service_ecs_security_group_231C6B1E" {
      + arn                    = (known after apply)
      + description            = "Internal ECS Security Group (Managed by Terraform)"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "required"
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = []
              + description      = "required"
              + from_port        = 80
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = (known after apply)
              + self             = false
              + to_port          = 4032
            },
        ]
      + name                   = (known after apply)
      + name_prefix            = "NotesAPI-Prod-ECSSecurityGroup"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all               = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + vpc_id                 = "vpc-867638e3"
    }

  # aws_security_group.rds_rds_security_group_B7738CEB will be created
  + resource "aws_security_group" "rds_rds_security_group_B7738CEB" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "required"
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "172.16.0.0/16",
                ]
              + from_port        = 5432
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 5432
                # (1 unchanged attribute hidden)
            },
        ]
      + name                   = (known after apply)
      + name_prefix            = "NotesAPI-Prod"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + tags_all               = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + vpc_id                 = "vpc-867638e3"
    }

  # aws_synthetics_canary.synthetics_synthetics_synthetic_check_query_0_99E4AE1B will be created
  + resource "aws_synthetics_canary" "synthetics_synthetics_synthetic_check_query_0_99E4AE1B" {
      + arn                      = (known after apply)
      + artifact_s3_location     = "s3://pocket-notesapi-prod-synthetic-checks/"
      + delete_lambda            = false
      + engine_arn               = (known after apply)
      + execution_role_arn       = (known after apply)
      + failure_retention_period = 31
      + handler                  = "synthetic.query"
      + id                       = (known after apply)
      + name                     = "notes-prod-query-0"
      + runtime_version          = "syn-nodejs-puppeteer-6.2"
      + s3_bucket                = "pocket-syntheticchecks-prod"
      + s3_key                   = "aws-synthetic-prod.zip"
      + source_location_arn      = (known after apply)
      + start_canary             = true
      + status                   = (known after apply)
      + success_retention_period = 31
      + tags_all                 = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + timeline                 = (known after apply)

      + run_config {
          + environment_variables = {
              + "GRAPHQL_ENDPOINT" = "notes.readitlater.com"
              + "GRAPHQL_JMESPATH" = "data.__typename"
              + "GRAPHQL_QUERY"    = "query { __typename }"
              + "GRAPHQL_RESPONSE" = "Query"
            }
          + memory_in_mb          = (known after apply)
          + timeout_in_seconds    = 180
        }

      + schedule {
          + expression = "rate(5 minutes)"
        }

      + vpc_config {
          + security_group_ids = [
              + "sg-2efb704a",
            ]
          + subnet_ids         = [
              + "subnet-610bdb3b",
              + "subnet-b2a036fa",
              + "subnet-cc66bde0",
              + "subnet-d09eb8ec",
            ]
          + vpc_id             = (known after apply)
        }
    }

  # aws_synthetics_canary.synthetics_synthetics_synthetic_check_uptime_0_4168D0DB will be created
  + resource "aws_synthetics_canary" "synthetics_synthetics_synthetic_check_uptime_0_4168D0DB" {
      + arn                      = (known after apply)
      + artifact_s3_location     = "s3://pocket-notesapi-prod-synthetic-checks/"
      + delete_lambda            = false
      + engine_arn               = (known after apply)
      + execution_role_arn       = (known after apply)
      + failure_retention_period = 31
      + handler                  = "synthetic.uptime"
      + id                       = (known after apply)
      + name                     = "notes-prod-uptime-0"
      + runtime_version          = "syn-nodejs-puppeteer-6.2"
      + s3_bucket                = "pocket-syntheticchecks-prod"
      + s3_key                   = "aws-synthetic-prod.zip"
      + source_location_arn      = (known after apply)
      + start_canary             = true
      + status                   = (known after apply)
      + success_retention_period = 31
      + tags_all                 = {
          + "app_code"       = "pocket"
          + "component_code" = "pocket-notesapi"
          + "costCenter"     = "Pocket"
          + "env_code"       = "prod"
          + "environment"    = "Prod"
          + "owner"          = "Pocket"
          + "service"        = "NotesAPI"
        }
      + timeline                 = (known after apply)

      + run_config {
          + environment_variables = {
              + "UPTIME_BODY" = "ok"
              + "UPTIME_URL"  = "notes.readitlater.com/.well-known/apollo/server-health"
            }
          + memory_in_mb          = (known after apply)
          + timeout_in_seconds    = 180
        }

      + schedule {
          + expression = "rate(5 minutes)"
        }

      + vpc_config {
          + security_group_ids = [
              + "sg-2efb704a",
            ]
          + subnet_ids         = [
              + "subnet-610bdb3b",
              + "subnet-b2a036fa",
              + "subnet-cc66bde0",
              + "subnet-d09eb8ec",
            ]
          + vpc_id             = (known after apply)
        }
    }

Plan: 54 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + ecs-application-url    = "notes.readitlater.com"
  + ecs-clusterName        = "NotesAPI-Prod"
  + ecs-codedeploy-app     = "NotesAPI-Prod-ECS"
  + ecs-codedeploy-group   = "NotesAPI-Prod-ECS"
  + ecs-serviceName        = "NotesAPI-Prod"
  + ecs-task-arn           = (known after apply)
  + ecs-task-containerName = "app"
  + ecs-task-containerPort = 4032
  + ecs-task-family        = "NotesAPI-Prod"

@kschelonka kschelonka enabled auto-merge (squash) November 20, 2024 17:43
@kschelonka kschelonka merged commit 601c1cb into main Nov 20, 2024
209 checks passed
@kschelonka kschelonka deleted the notes-api-infra branch November 20, 2024 17:54
Copy link

🎉 This PR is included in version @pocket-tools/terraform-modules-v5.17.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/ts-logger-v1.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/lambda-secrets-v1.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/sentry-v1.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/feature-flags-client-v1.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/jwt-utils-v1.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/tracing-v1.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/image-utils-v1.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/event-bridge-v1.8.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link

🎉 This PR is included in version @pocket-tools/apollo-utils-v3.12.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants