provider "aws" {
  region  = var.region
  profile = var.account
}

terraform {
  backend "s3" {}
}

data "aws_caller_identity" "current" {}

locals {
  name = "o11y-${var.env}-${var.logical_region_name}"
}

locals {
  aws_account_id = data.aws_caller_identity.current.account_id

  subnets         = cidrsubnets(var.cidr, 4, 4, 4, 4, 4, 4, 4, 4) # 每个 subnet 是 /20（/16 + 4）
  public_subnets  = slice(local.subnets, 0, 3)
  private_subnets = slice(local.subnets, 4, 4 + 3)
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name            = "${local.name}-vpc"
  cidr            = var.cidr
  azs             = split(",", var.availability_zones)
  private_subnets = local.private_subnets
  public_subnets  = local.public_subnets

  enable_nat_gateway         = true
  single_nat_gateway         = true
  manage_default_network_acl = false
  public_subnet_tags = {
    "kubernetes.io/role/elb"              = "1"
    "kubernetes.io/cluster/${local.name}" = "shared"
    "SubnetType"                          = "Public"
  }
  private_subnet_tags = {
    "kubernetes.io/role/internal-elb"     = "1"
    "kubernetes.io/cluster/${local.name}" = "shared"
    "SubnetType"                          = "Private"
  }

  tags = var.tags
}

data "aws_subnet" "vpc_subnets" {
  count = length(module.vpc.private_subnets)
  id    = module.vpc.private_subnets[count.index]
}

# 根据指定的 az 找到其对应的 subnet_id
locals {
  worker_node_group_subnet_ids = [
    for subnet in data.aws_subnet.vpc_subnets : subnet.id
    if contains(var.node_groups.worker.availability_zones, subnet.availability_zone)
  ]
}

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.0"

  cluster_name                         = local.name
  cluster_version                      = var.k8s_version
  cluster_endpoint_private_access      = true
  cluster_endpoint_public_access       = true
  enable_irsa                          = true
  create_cloudwatch_log_group          = false
  create_kms_key                       = false
  cluster_encryption_config            = {}
  cluster_endpoint_public_access_cidrs = var.public_access_cidrs

  create_iam_role      = false
  iam_role_arn         = "arn:aws:iam::${local.aws_account_id}:role/${var.cluster_role_name}"
  create_node_iam_role = false

  cluster_addons = {
    vpc-cni = {
      resolve_conflicts = "OVERWRITE"
      most_recent       = true
      configuration_values = jsonencode({
        env = {
          ENABLE_PREFIX_DELEGATION = "true"
        }
      })
    }
    coredns = {
      most_recent = true
    }
    kube-proxy = {
      most_recent = true
    }
    aws-ebs-csi-driver = {
      most_recent = true
    }
    metrics-server = {
      most_recent = true
    }
  }

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_group_defaults = {
    ami_type                   = "BOTTLEROCKET_x86_64"
    min_size                   = 1
    max_size                   = 10
    desired_size               = 3
    max_pods_per_node          = 110
    subnet_ids                 = local.worker_node_group_subnet_ids
    iam_role_arn               = "arn:aws:iam::${local.aws_account_id}:role/${var.node_role_name}"
    create_iam_role            = false
    iam_role_attach_cni_policy = false
  }

  eks_managed_node_groups                  = var.node_groups
  enable_cluster_creator_admin_permissions = true

  tags = merge({
    environment = var.env
  }, var.tags)
}

resource "aws_security_group" "clinic_http" {
  name        = "${local.name}-clinic-http-sg"
  description = "Security group for VPC endpoint to allow HTTP traffic"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = [var.cidr]
  }

  egress = []
}

resource "aws_vpc_endpoint" "clinic" {
  service_name        = var.clinic_endpoint_service_name
  service_region      = "us-west-2"
  vpc_endpoint_type   = "Interface"
  private_dns_enabled = false

  vpc_id             = module.vpc.vpc_id
  subnet_ids         = module.vpc.private_subnets
  security_group_ids = [aws_security_group.clinic_http.id]

  tags = merge({
    Name        = "${local.name}-clinic"
    ManagedBy   = "PingCAP"
    environment = var.env
  }, var.tags)
}
