# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# Data Source (https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region)
data "aws_region" "current" {}

# Data Source (https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity)
data "aws_caller_identity" "current" {}


# Uncomment if you are using an ALB rather than the default NLB and wish for access logging
# NLB is required for any other protocol than HTTP/HTTPS, e.g. CICS

#resource "aws_s3_bucket" "elb_logs" {
#  # checkov:skip=CKV_AWS_145:SSE-S3 is sufficient for this data
#  # checkov:skip=CKV_AWS_21:S3 Versioning is not appropriate for ALB log storage
#  # checkov:skip=CKV_AWS_18:Access logging is not required for data in this S3 Bucket
#  # checkov:skip=CKV_AWS_144:CRR is not required for this data
#  bucket = "${var.stack_prefix}-elb-access-logs-${data.aws_caller_identity.current.account_id}"
#}
#
#resource "aws_s3_bucket_lifecycle_configuration" "elb_logs_lifecycle" {
#  bucket = aws_s3_bucket.elb_logs.id
#
#  rule {
#    id = "expire-after-1-month"
#
#    expiration {
#      days = 31
#    }
#
#    status = "Enabled"
#  }
#}
#
#resource "aws_s3_bucket_server_side_encryption_configuration" "elb_logs_encryption" {
#  bucket = aws_s3_bucket.elb_logs.bucket
#
#  rule {
#    apply_server_side_encryption_by_default {
#      sse_algorithm     = "AES256"
#    }
#  }
#}
#
#resource "aws_s3_bucket_public_access_block" "elb_logs_bpa" {
#  bucket = aws_s3_bucket.elb_logs.id
#
#  block_public_acls       = true
#  block_public_policy     = true
#  ignore_public_acls      = true
#  restrict_public_buckets = true
#}
#
## The account delivering logs is owned by AWS, details can be found here
## https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html#attach-bucket-policy
#data "aws_iam_policy_document" "allow_elb_access_logging" {
#  statement {
#    effect = "Allow"
#    actions = [ "s3:PutObject" ]
#    principals {
#      type = "Service"
#      identifiers = [
#        "delivery.logs.amazonaws.com"
#      ]
#    }
#    resources = [
#      "arn:aws:s3:::${aws_s3_bucket.elb_logs.id}/bluage/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
#    ]
#  }
#  statement {
#    effect = "Allow"
#    actions = [ "s3:GetBucketAcl" ]
#    principals {
#      type = "Service"
#      identifiers = [
#        "delivery.logs.amazonaws.com"
#      ]
#    }
#    resources = [
#      "arn:aws:s3:::${aws_s3_bucket.elb_logs.id}"
#    ]
#  }
#}
#
#resource "aws_s3_bucket_policy" "attach_elb_access_logging_policy" {
#  bucket = aws_s3_bucket.elb_logs.id
#  policy = data.aws_iam_policy_document.allow_elb_access_logging.json
#}

resource "aws_lb" "realtime_interface_elb" {
  # checkov:skip=CKV_AWS_91:NLBs do not support access logging
  # checkov:skip=CKV_AWS_150:Deletion protection can be enabled if required
  name                             = "${var.stack_prefix}-elb"
  internal                         = true
  load_balancer_type               = "network"
  enable_deletion_protection       = false
  subnets                          = var.public_subnets
  enable_cross_zone_load_balancing = true

  # Access logs are not written for NLBs

  #access_logs {
  #  bucket  = aws_s3_bucket.elb_logs.bucket
  #  prefix  = "bluage"
  #  enabled = true
  #}

  tags = {
    Name = "${var.stack_prefix}-elb"
  }
}

# Adjust the TCP port as required
resource "aws_lb_target_group" "realtime_interface_tg" {
  name        = "${var.stack_prefix}-tg"
  port        = 3090
  protocol    = "TCP_UDP"
  target_type = "ip"
  vpc_id      = var.vpc_id

  health_check {
    port                = "traffic-port"
    protocol            = "TCP"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}

resource "aws_lb_listener" "realtime_interface_listener" {
  load_balancer_arn = aws_lb.realtime_interface_elb.arn
  port              = "3090"
  protocol          = "TCP_UDP"

  default_action {
    type = "forward"
    target_group_arn = aws_lb_target_group.realtime_interface_tg.arn
  }
}

# Uncomment if an Alias record is needed in Route53
#resource "aws_route53_record" "realtime_interface_r53_alias" {
#  zone_id = "AZ12345678910"
#  name    = "dns_record_name"
#  type    = "A"
#
#  alias {
#    name                   = aws_lb.realtime_interface_elb.dns_name
#    zone_id                = aws_lb.realtime_interface_elb.zone_id
#    evaluate_target_health = true
#  }
#}

resource "aws_ecs_task_definition" "realtime_ecs_service_definition" {
  # checkov:skip=CKV_AWS_336:Read-only root filesystem is not supported in this example
  family                   = "${var.stack_prefix}-realtime-interface"
  task_role_arn            = var.realtime_ecs_service_role_arn
  execution_role_arn       = var.realtime_ecs_service_execution_role_arn
  network_mode             = "awsvpc"
  requires_compatibilities = [ "FARGATE" ]
  cpu                      = var.task_cpu_allocation
  memory                   = var.task_memory_allocation
  container_definitions = <<DEFINITION
[
    {
      "dnsSearchDomains": null,
      "environmentFiles": null,
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
            "awslogs-group": "${var.cloudwatch_log_group_name}",
            "awslogs-region": "${data.aws_region.current.name}",
            "awslogs-stream-prefix": "/aws/ecs"
        }
      },
      "entryPoint": [
        "/bin/bash",
        "-l",
        "-c"
      ],
      "portMappings": [
        {
          "containerPort": 3090,
          "hostPort": 3090,
          "protocol": "tcp"
        }
      ],
      "command": [
        "./wrapper.sh REALTIME"
      ],
      "linuxParameters": null,
      "cpu": 0,
      "environment": [
        {
          "name": "S3_INPUT_BUCKET",
          "value": "${var.input_s3_bucket_id}"
        },
        {
          "name": "S3_OUTPUT_BUCKET",
          "value": "${var.input_s3_bucket_id}"
        },
        {
          "name": "DB_NAME",
          "value": "${var.database_name}"
        },
        {
          "name": "JAVA_MAX_HEAP",
          "value": "${var.java_max_heap}"
        },
        {
          "name": "DEBUG_ENABLED",
          "value": "${var.debug_enabled}"
        },
        {
          "name": "FIXED_EXPORT_TIME",
          "value": "${var.force_execution_time}"
        },
        {
          "name": "JDBC_PARAMETERS",
          "value": "${var.jdbc_parameters}"
        }
      ],
      "resourceRequirements": null,
      "ulimits": null,
      "dnsServers": null,
      "mountPoints": [],
      "workingDirectory": "/usr/share",
      "secrets": [
          {
              "valueFrom": "${var.user_secret_arn}",
              "name": "DB_PASSWORD"
          },
          {
              "valueFrom": "${var.ssm_rds_endpoint_arn}",
              "name": "RDS_ENDPOINT"
          }           
      ],
      "dockerSecurityOptions": null,
      "memory": null,
      "memoryReservation": null,
      "volumesFrom": [],
      "stopTimeout": 30,
      "image": "${var.container_image}",
      "startTimeout": 30,
      "firelensConfiguration": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": null,
      "hostname": null,
      "extraHosts": null,
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": null,
      "systemControls": null,
      "privileged": null,
      "name": "bluage_realtime_interface"
    }
]
DEFINITION

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_ecs_service" "realtime_ecs_Service" {
  name                               = "${var.stack_prefix}-realtime-ecs-service"
  task_definition                    = aws_ecs_task_definition.realtime_ecs_service_definition.arn
  desired_count                      = var.container_count
  deployment_maximum_percent         = 200
  deployment_minimum_healthy_percent = 100
  health_check_grace_period_seconds  = 30
  launch_type                        = "FARGATE"
  enable_ecs_managed_tags            = true
  cluster                            = var.ecs_cluster_arn

  load_balancer {
    container_name   = "bluage_realtime_interface"
    container_port   = 3090
    target_group_arn = aws_lb_target_group.realtime_interface_tg.arn
  }

  # https://www.terraform.io/docs/providers/aws/r/ecs_service.html#network_configuration
  network_configuration {
    security_groups  = [
      var.ecs_service_sg_id,
      var.rds_sg_id
    ]
    subnets          = var.private_subnets
  }

  deployment_circuit_breaker {
    enable   = true
    rollback = true
  }

  lifecycle {
    ignore_changes = [
      desired_count
    ]
  }
}