AWSTemplateFormatVersion: '2010-09-09'
Description: 'Creates the EKS cluster IAM role and EKS cluster with Remote Node Network and Remote Pod Network for hybrid nodes'

Metadata:
  Version:
    Number: "v0.0.7"

Parameters:
  ClusterName:
    Type: String
  ClusterRoleName:
    Type: String
    Default: 'EKSClusterRole'
  VpcId:
    Type: String
    Description: The VPC that a Security Group will be created in for the EKS Cluster, required if a SecurityGroupId is not configured
    Default: ''
  SubnetId1:
    Type: String
    Description: The ID of the first subnet in your VPC where EKS will attach ENIs
  SubnetId2:
    Type: String
    Description: The ID of the second subnet in your VPC where EKS will attach ENIs
  SecurityGroupId:
    Type: String
    Description: The ID of the security group that enables ingress for your RemoteNodeCIDR and optionally RemotePodCIDR. This will override the creeation of a SecurityGroup using VpcId.
    Default: ''
  RemoteNodeCIDR:
    Type: String
    Description: The CIDR blocks for hybrid nodes
  RemotePodCIDR:
    Type: String
    Description: The CIDR blocks for workloads running on hybrid nodes
    Default: ''
  ClusterAuthMode:
    Type: String
    Description: The cluster authentication mode. Valid values are one of [API, API_AND_CONFIG_MAP]
    Default: 'API_AND_CONFIG_MAP'
    AllowedValues:
      - 'API_AND_CONFIG_MAP'
      - 'API'
  ClusterEndpointConnectivity:
    Type: String
    Description: The cluster endpoint connectivity mode. Valid values are one of [Public, Private].
    Default: 'Private'
    AllowedValues:
      - 'Private'
      - 'Public'
  K8sVersion:
    Type: String
    Description: The Kubernetes minor version for the EKS cluster
    Default: '1.31'

Conditions:
  HasRemotePodCIDR: !Not [!Equals [!Ref RemotePodCIDR, '']]
  HasPublicAccess: !Equals [!Ref ClusterEndpointConnectivity, 'Public']
  HasPrivateAccess: !Equals [!Ref ClusterEndpointConnectivity, 'Private']
  NoSecurityGroupId: !Equals [!Ref SecurityGroupId, '']

Resources:
  EKSClusterRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: eks.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
      RoleName: !Ref ClusterRoleName

  EKSClusterSG:
    Condition: NoSecurityGroupId
    Type: AWS::EC2::SecurityGroup
    DeletionPolicy: Delete
    Properties:
      GroupDescription: Security group for ingress from hybrid nodes to EKS control plane
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref RemoteNodeCIDR
        - !If
          - HasRemotePodCIDR
          - IpProtocol: tcp
            FromPort: 443
            ToPort: 443
            CidrIp: !Ref RemotePodCIDR
          - !Ref "AWS::NoValue"

  EKSCluster:
    Type: AWS::EKS::Cluster
    DependsOn: EKSClusterRole
    Properties:
      Name: !Ref ClusterName
      Version: !Ref K8sVersion
      RoleArn: !GetAtt EKSClusterRole.Arn
      AccessConfig: 
        AuthenticationMode: !Ref ClusterAuthMode
      ResourcesVpcConfig:
        SecurityGroupIds:
          - !If [NoSecurityGroupId, !Ref EKSClusterSG, !Ref SecurityGroupId]
        SubnetIds: 
          - !Ref SubnetId1
          - !Ref SubnetId2
        EndpointPublicAccess: !If [HasPublicAccess, true, false]
        EndpointPrivateAccess: !If [HasPrivateAccess, true, false]
      RemoteNetworkConfig:
        RemoteNodeNetworks:
          - Cidrs: [!Ref RemoteNodeCIDR]
        RemotePodNetworks: !If
          - HasRemotePodCIDR
          - [Cidrs: [!Ref RemotePodCIDR]]
          - !Ref 'AWS::NoValue'

Outputs:
  EKSClusterName:
    Description: Name for the EKS Cluster
    Value: !Ref EKSCluster
    Export:
      Name: EKSCluster

  EKSClusterARN:
    Description: ARN for the EKS Cluster
    Value: !GetAtt EKSCluster.Arn
    Export:
      Name: EKSClusterARN

  EKSClusterRoleName:
    Description: Name for the EKS Cluster Role
    Value: !Ref EKSClusterRole
    Export:
      Name: EKSClusterRole
  
  EKSClusterRoleARN:
    Description: ARN for the EKS Cluster Role
    Value: !GetAtt EKSClusterRole.Arn
    Export:
      Name: EKSClusterRoleARN
