---
AWSTemplateFormatVersion: "2010-09-09"
Description: "Amazon EKS VPC"

Parameters:
  VpcBlock:
    Type: String
    Default: 192.168.0.0/16 #Todo: Take this input from user
    Description: The CIDR range for the VPC. This should be a valid private (RFC 1918) CIDR range.

  Subnet01Block:
    Type: String
    Default: 192.168.64.0/18
    Description: CidrBlock for subnet 01 within the VPC

  Subnet02Block:
    Type: String
    Default: 192.168.128.0/18
    Description: CidrBlock for subnet 02 within the VPC

  Subnet03Block:
    Type: String
    Default: 192.168.192.0/18
    Description: CidrBlock for subnet 03 within the VPC

  ClusterName:
    Type: String
    Default: my-first-cluster
    Description: "EKS cluster"

  NodeImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI id for the node instances.

  S3BucketName:
    Type: String
    Description: "S3 bucket for storing session logs"

  NodeInstanceType:
    Description: EC2 instance type for the node instances
    Type: String
    Default: t3.large
    ConstraintDescription: Must be a valid EC2 instance type

  NodeAutoScalingGroupMinSize:
    Type: Number
    Description: Minimum size of Node Group ASG.
    Default: 1

  NodeAutoScalingGroupMaxSize:
    Type: Number
    Description: Maximum size of Node Group ASG.
    Default: 3

  NodeAutoScalingGroupMinSizeWindows:
    Type: Number
    Description: Minimum size of Windows Node Group ASG.
    Default: 0

  NodeAutoScalingGroupDesiredSizeWindows:
    Type: Number
    Description: Desired size of Windows Node Group ASG.
    Default: 1

  NodeVolumeSize:
    Type: Number
    Description: Node volume size
    Default: 10

  BootstrapArguments:
    Description: Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami
    Default: ""
    Type: String

  NodeGroupName:
    Description: Unique identifier for the Linux Node Group.
    Type: String

  NodeGroupNameWindows:
    Description: Unique identifier for the Windows Node Group.
    Type: String

  ClusterAutoUpgrade:
    Type: String
    Default: "false"
    AllowedValues:
      - "true"
      - "false"
    Description: Enable or disable cluster auto-upgrade

Conditions:
  IsClusterAutoUpgrade: !Equals [ !Ref ClusterAutoUpgrade, "true" ]

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Worker Network Configuration"
        Parameters:
          - ClusterName
      - Label:
          default: "Cluster Configuration"
        Parameters:
          - ClusterName
      - Label:
          default: "Worker Node Configuration"
        Parameters:
          - NodeGroupName
          - NodeAutoScalingGroupMinSize
          - NodeAutoScalingGroupMaxSize
          - NodeInstanceType
          - NodeImageId
          - NodeVolumeSize
          - BootstrapArguments

Resources:
  ControlPlaneSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster communication with worker nodes
      VpcId: !Ref VPC
      Tags: []

  ClusterRole:
    Type: AWS::IAM::Role
    Properties:
      Description: "Allows EKS to manage clusters on your behalf"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - eks.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
        - arn:aws:iam::aws:policy/AmazonEKSServicePolicy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonEKSVPCResourceController
      Tags: []

  EKSCluster:
    Type: AWS::EKS::Cluster
    DependsOn:
      - ClusterRole
      - ControlPlaneSecurityGroup
    Properties:
      Name: !Ref ClusterName
      # Version: "1.10"
      RoleArn: !GetAtt ClusterRole.Arn
      ResourcesVpcConfig:
        SecurityGroupIds:
          - !Join [",", [!Ref ControlPlaneSecurityGroup]]
        SubnetIds: []
      UpgradePolicy:
        SupportType: !If [IsClusterAutoUpgrade, "STANDARD", "EXTENDED"]

  NodeInstanceRole:
    Type: AWS::IAM::Role
    DependsOn:
      - EKSCluster
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
        - arn:aws:iam::aws:policy/AmazonEKSVPCResourceController
      Tags: []

  NodeGroup:
    Type: AWS::EKS::Nodegroup
    DependsOn:
      - EKSCluster
    Properties:
      CapacityType: "ON_DEMAND"
      ClusterName: !Ref ClusterName
      InstanceTypes:
        - !Ref NodeInstanceType
      Labels:
        createdBy: Browserstack
        managedBy: Browserstack
      NodegroupName: !Ref NodeGroupName
      NodeRole: !GetAtt NodeInstanceRole.Arn
      ScalingConfig:
        {
          DesiredSize: !Ref NodeAutoScalingGroupMinSize,
          MinSize: !Ref NodeAutoScalingGroupMinSize,
          MaxSize: !Ref NodeAutoScalingGroupMaxSize,
        }
      Subnets: []
      Tags: []

  NodeGroupWindows:
    Type: AWS::EKS::Nodegroup
    DependsOn:
      - EKSCluster
    Properties:
      CapacityType: "ON_DEMAND"
      ClusterName: !Ref ClusterName
      AmiType: WINDOWS_FULL_2022_x86_64
      InstanceTypes:
        - !Ref NodeInstanceType
      Labels:
        createdBy: Browserstack
        managedBy: Browserstack
      NodegroupName: !Ref NodeGroupNameWindows
      NodeRole: !GetAtt NodeInstanceRole.Arn
      ScalingConfig:
        {
          DesiredSize: !Ref NodeAutoScalingGroupDesiredSizeWindows,
          MinSize: !Ref NodeAutoScalingGroupMinSizeWindows,
          MaxSize: !Ref NodeAutoScalingGroupMaxSize,
        }
      Subnets: []
      Tags: []

Outputs:
  VpcId:
    Description: The VPC Id
    Value: !Ref VPC

  SubnetIds:
    Description: All subnets in the VPC
    Value: !Join [",", []]

  SecurityGroups:
    Description: Security group for the cluster control plane communication with worker nodes
    Value: !Join [",", [!Ref ControlPlaneSecurityGroup]]

  EKSClusterRole:
    Description: Role to manage EKS cluster
    Value: !GetAtt ClusterRole.Arn

  EKSClusterName:
    Description: EKS Cluster
    Value: !Ref EKSCluster

  NodeInstanceRole:
    Description: The node instance role
    Value: !GetAtt NodeInstanceRole.Arn
