{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "OwnerName": {
            "Type": "String"
        },
        "OwnerEmail": {
            "Type": "String"
        },
        "AZIdx": {
            "Type": "Number",
            "Default": 0,
            "MinValue": 0,
            "MaxValue": 2,
            "Description": "Resources from which AZ"
        },
        "BastionRoleArn": {
            "Type": "String",
            "Default": "arn:aws:iam::373771598235:role/course-303-node-role",
            "Description": "IAM role ARN for bastion (granted EKS cluster access)"
        }
    },
    "Mappings": {
        "ValueMap": {
            "us-west-2": {
                "AMI": "ami-054982af01587408e",
                "key": "pe-class-key-oregon",
                "ud": "#!/bin/bash\n"
            },
            "ap-southeast-1": {
                "AMI": "ami-0ef09bfe6af6b354a",
                "key": "pe-class-key-singapore",
                "ud": "#!/bin/bash\n"
            },
            "ap-northeast-1": {
                "AMI": "ami-0b72961e65bace919",
                "key": "pe-class-key-tokyo",
                "ud": "#!/bin/bash\n"
            },
            "eu-central-1": {
                "AMI": "ami-02a5902e4e79bd9d8",
                "key": "pe-class-key-frankfurt",
                "ud": "#!/bin/bash\n"
            }
        }
    },
    "Resources": {
        "LoadBalancerControllerRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Fn::Sub": [
                        "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Federated\":\"${OIDCArn}\"},\"Action\":\"sts:AssumeRoleWithWebIdentity\",\"Condition\":{\"StringEquals\":{\"${OIDCProvider}:sub\":\"system:serviceaccount:kube-system:aws-load-balancer-controller\",\"${OIDCProvider}:aud\":\"sts.amazonaws.com\"}}}]}",
                        {
                            "OIDCArn": {
                                "Ref": "EksOIDCProvider"
                            },
                            "OIDCProvider": {
                                "Fn::Select": [
                                    1,
                                    {
                                        "Fn::Split": [
                                            "https://",
                                            {
                                                "Fn::GetAtt": [
                                                    "EKSCluster",
                                                    "OpenIdConnectIssuerUrl"
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::373771598235:policy/demo_010o-load-balancer-controller-policy"
                ]
            },
            "DependsOn": [
                "EksOIDCProvider"
            ]
        },
        "TG": {
            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
            "Properties": {
                "TargetType": "ip",
                "HealthCheckEnabled": true,
                "HealthCheckProtocol": "TCP",
                "HealthCheckPort": "10080",
                "HealthCheckIntervalSeconds": 10,
                "HealthyThresholdCount": 2,
                "UnhealthyThresholdCount": 2,
                "Port": 4000,
                "Protocol": "TCP",
                "TargetGroupAttributes": [
                    {
                        "Key": "deregistration_delay.timeout_seconds",
                        "Value": "60"
                    },
                    {
                        "Key": "preserve_client_ip.enabled",
                        "Value": "true"
                    }
                ],
                "VpcId": {
                    "Ref": "DemoVPC"
                }
            }
        },
        "NLB": {
            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
            "Properties": {
                "Type": "network",
                "Name": {
                    "Ref": "OwnerName"
                },
                "Scheme": "internal",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    },
                    {
                        "Ref": "SN2"
                    }
                ]
            }
        },
        "LSNR": {
            "Type": "AWS::ElasticLoadBalancingV2::Listener",
            "Properties": {
                "DefaultActions": [
                    {
                        "Type": "forward",
                        "ForwardConfig": {
                            "TargetGroups": [
                                {
                                    "TargetGroupArn": {
                                        "Ref": "TG"
                                    }
                                }
                            ]
                        }
                    }
                ],
                "LoadBalancerArn": {
                    "Ref": "NLB"
                },
                "Port": 4000,
                "Protocol": "TCP"
            }
        },
        "DemoIGW": {
            "Type": "AWS::EC2::InternetGateway",
            "Properties": {
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    }
                ]
            },
            "DependsOn": [
                "DemoVPC"
            ]
        },
        "DemoVPC": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.90.0.0/16",
                "EnableDnsSupport": "true",
                "EnableDnsHostnames": "true",
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": {
                            "Ref": "OwnerName"
                        }
                    }
                ]
            }
        },
        "IGWA": {
            "Type": "AWS::EC2::VPCGatewayAttachment",
            "Properties": {
                "InternetGatewayId": {
                    "Ref": "DemoIGW"
                },
                "VpcId": {
                    "Ref": "DemoVPC"
                }
            },
            "DependsOn": [
                "DemoIGW"
            ]
        },
        "PublicRouteTable": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "DemoVPC"
                },
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": "PE Quick Demo Public Route"
                    }
                ]
            }
        },
        "PublicRoute": {
            "Type": "AWS::EC2::Route",
            "Properties": {
                "DestinationCidrBlock": "0.0.0.0/0",
                "GatewayId": {
                    "Ref": "DemoIGW"
                },
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                }
            },
            "DependsOn": [
                "IGWA"
            ]
        },
        "SN1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "DemoVPC"
                },
                "CidrBlock": "10.90.1.0/24",
                "AvailabilityZone": {
                    "Fn::Select": [
                        0,
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "MapPublicIpOnLaunch": true,
                "PrivateDnsNameOptionsOnLaunch": {
                    "EnableResourceNameDnsAAAARecord": false,
                    "EnableResourceNameDnsARecord": true,
                    "HostnameType": "ip-name"
                },
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "OwnerName"
                                    },
                                    "subnet",
                                    "1"
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "SN2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "DemoVPC"
                },
                "CidrBlock": "10.90.2.0/24",
                "AvailabilityZone": {
                    "Fn::Select": [
                        1,
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "MapPublicIpOnLaunch": true,
                "PrivateDnsNameOptionsOnLaunch": {
                    "EnableResourceNameDnsAAAARecord": false,
                    "EnableResourceNameDnsARecord": true,
                    "HostnameType": "ip-name"
                },
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "OwnerName"
                                    },
                                    "subnet",
                                    "2"
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "SN3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "VpcId": {
                    "Ref": "DemoVPC"
                },
                "CidrBlock": "10.90.3.0/24",
                "AvailabilityZone": {
                    "Fn::Select": [
                        2,
                        {
                            "Fn::GetAZs": ""
                        }
                    ]
                },
                "MapPublicIpOnLaunch": true,
                "PrivateDnsNameOptionsOnLaunch": {
                    "EnableResourceNameDnsAAAARecord": false,
                    "EnableResourceNameDnsARecord": true,
                    "HostnameType": "ip-name"
                },
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "OwnerName"
                                    },
                                    "subnet",
                                    "3"
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "SRTA1": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "SN1"
                },
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                }
            }
        },
        "SRTA2": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "SN2"
                },
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                }
            }
        },
        "SRTA3": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "SN3"
                },
                "RouteTableId": {
                    "Ref": "PublicRouteTable"
                }
            }
        },
        "DemoSG": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Allow nodes communication.",
                "VpcId": {
                    "Ref": "DemoVPC"
                },
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 22,
                        "ToPort": 22,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 2379,
                        "ToPort": 2379,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 4000,
                        "ToPort": 4002,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 3000,
                        "ToPort": 3000,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "icmp",
                        "FromPort": -1,
                        "ToPort": -1,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "-1",
                        "CidrIp": "10.90.0.0/16",
                        "Description": "Allow all traffic within VPC (EC2 nodes and pods)"
                    }
                ],
                "SecurityGroupEgress": [
                    {
                        "IpProtocol": "-1",
                        "CidrIp": "0.0.0.0/0",
                        "Description": "Allow all outbound (bastion and worker nodes)"
                    }
                ],
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        }
                    },
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "OwnerName"
                                    },
                                    "-sg"
                                ]
                            ]
                        }
                    }
                ]
            }
        },
        "IRule": {
            "Type": "AWS::EC2::SecurityGroupIngress",
            "Properties": {
                "IpProtocol": "-1",
                "SourceSecurityGroupId": {
                    "Fn::GetAtt": [
                        "DemoSG",
                        "GroupId"
                    ]
                },
                "GroupId": {
                    "Fn::GetAtt": [
                        "DemoSG",
                        "GroupId"
                    ]
                }
            }
        },
        "EKSCluster": {
            "Type": "AWS::EKS::Cluster",
            "Properties": {
                "Name": {
                    "Fn::Sub": "${AWS::StackName}-eks"
                },
                "Version": "1.35",
                "DeletionProtection": false,
                "RoleArn": "arn:aws:iam::373771598235:role/demo_010o-eks-cluster-role",
                "ResourcesVpcConfig": {
                    "SubnetIds": [
                        {
                            "Ref": "SN1"
                        },
                        {
                            "Ref": "SN2"
                        },
                        {
                            "Ref": "SN3"
                        }
                    ],
                    "SecurityGroupIds": [
                        {
                            "Ref": "DemoSG"
                        }
                    ],
                    "EndpointPublicAccess": true,
                    "EndpointPrivateAccess": true
                },
                "AccessConfig": {
                    "AuthenticationMode": "API_AND_CONFIG_MAP",
                    "BootstrapClusterCreatorAdminPermissions": true
                }
            }
        },
        "EksOIDCProvider": {
            "Type": "AWS::IAM::OIDCProvider",
            "Properties": {
                "Url": {
                    "Fn::GetAtt": [
                        "EKSCluster",
                        "OpenIdConnectIssuerUrl"
                    ]
                },
                "ClientIdList": [
                    "sts.amazonaws.com"
                ],
                "ThumbprintList": [
                    "9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup1": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tidb-1",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.large"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tidb",
                    "az": "az1"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tidb",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup2": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tidb-2",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN2"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.large"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tidb",
                    "az": "az2"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tidb",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup3": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tikv-1",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.xlarge"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tikv",
                    "az": "az1"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tikv",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup4": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tikv-2",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN2"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.xlarge"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tikv",
                    "az": "az2"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tikv",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup5": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tikv-3",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN3"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.xlarge"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tikv",
                    "az": "az3"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tikv",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup6": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "pd-1",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.large"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "pd",
                    "az": "az1"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "pd",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup7": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "pd-2",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN2"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.large"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "pd",
                    "az": "az2"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "pd",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup8": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "pd-3",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN3"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.large"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "pd",
                    "az": "az3"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "pd",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup9": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "admin",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "c5.xlarge"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "admin",
                    "az": "az1"
                }
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EKSNodeGroup10": {
            "Type": "AWS::EKS::Nodegroup",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "NodegroupName": "tiflash-1",
                "NodeRole": "arn:aws:iam::373771598235:role/demo_010o-eks-node-group-role",
                "Subnets": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "ScalingConfig": {
                    "MinSize": 1,
                    "MaxSize": 1,
                    "DesiredSize": 1
                },
                "InstanceTypes": [
                    "r5.xlarge"
                ],
                "AmiType": "AL2023_x86_64_STANDARD",
                "Labels": {
                    "dedicated": "tiflash",
                    "az": "az1"
                },
                "Taints": [
                    {
                        "Key": "dedicated",
                        "Value": "tiflash",
                        "Effect": "NO_SCHEDULE"
                    }
                ]
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "PodIdentityAgentAddon": {
            "Type": "AWS::EKS::Addon",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "AddonName": "eks-pod-identity-agent",
                "ResolveConflicts": "OVERWRITE"
            },
            "DependsOn": [
                "EKSCluster"
            ]
        },
        "EBSCSIAddon": {
            "Type": "AWS::EKS::Addon",
            "Properties": {
                "ClusterName": {
                    "Ref": "EKSCluster"
                },
                "AddonName": "aws-ebs-csi-driver",
                "ResolveConflicts": "OVERWRITE",
                "PodIdentityAssociations": [
                    {
                        "RoleArn": "arn:aws:iam::373771598235:role/demo_010o-ebs-csi-driver-role",
                        "ServiceAccount": "ebs-csi-controller-sa"
                    }
                ]
            },
            "DependsOn": [
                "EKSNodeGroup1",
                "EKSNodeGroup2",
                "EKSNodeGroup3",
                "EKSNodeGroup4",
                "EKSNodeGroup5",
                "EKSNodeGroup6",
                "EKSNodeGroup7",
                "EKSNodeGroup8",
                "EKSNodeGroup9",
                "EKSNodeGroup10"
            ]
        },
        "EKSBastionAccessLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Runtime": "python3.12",
                "Handler": "index.handler",
                "Role": "arn:aws:iam::373771598235:role/demo_010o-eks-bastion-access-lambda-role",
                "Timeout": 60,
                "Code": {
                    "ZipFile": {
                        "Fn::Sub": [
                            "import json\nimport boto3\nimport urllib.request\nfrom botocore.exceptions import ClientError\n\ndef send_response(event, context, status, reason=None, data=None):\n    body = json.dumps({'Status': status, 'Reason': reason or 'OK', 'PhysicalResourceId': event.get('PhysicalResourceId', event['LogicalResourceId']), 'StackId': event['StackId'], 'RequestId': event['RequestId'], 'LogicalResourceId': event['LogicalResourceId'], 'Data': data or {}})\n    req = urllib.request.Request(event['ResponseURL'], data=body.encode(), method='PUT', headers={'Content-Type': ''})\n    urllib.request.urlopen(req)\n\ndef handler(event, context):\n    eks = boto3.client('eks')\n    props = event.get('ResourceProperties', {})\n    cluster = props.get('ClusterName')\n    principal = props.get('PrincipalArn')\n    policy_arn = 'arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy'\n    try:\n        if event['RequestType'] in ('Create', 'Update'):\n            try:\n                eks.create_access_entry(clusterName=cluster, principalArn=principal)\n            except ClientError as e:\n                if e.response.get('Error', {}).get('Code') != 'ResourceInUseException':\n                    raise\n            \n            eks.associate_access_policy(clusterName=cluster, principalArn=principal, policyArn=policy_arn, accessScope={'type': 'cluster'})\n        elif event['RequestType'] == 'Delete':\n            try:\n                eks.disassociate_access_policy(clusterName=cluster, principalArn=principal, policyArn=policy_arn)\n            except Exception:\n                pass\n            eks.delete_access_entry(clusterName=cluster, principalArn=principal)\n        send_response(event, context, 'SUCCESS')\n    except Exception as e:\n        send_response(event, context, 'FAILED', str(e))\n",
                            {}
                        ]
                    }
                }
            }
        },
        "EKSBastionAccessLambdaPermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "FunctionName": {
                    "Ref": "EKSBastionAccessLambda"
                },
                "Action": "lambda:InvokeFunction",
                "Principal": "cloudformation.amazonaws.com"
            }
        },
        "EKSBastionAccessEntry": {
            "Type": "AWS::CloudFormation::CustomResource",
            "Properties": {
                "ServiceToken": {
                    "Fn::GetAtt": [
                        "EKSBastionAccessLambda",
                        "Arn"
                    ]
                },
                "ClusterName": {
                    "Fn::Sub": "${AWS::StackName}-eks"
                },
                "PrincipalArn": {
                    "Ref": "BastionRoleArn"
                }
            },
            "DependsOn": [
                "EKSCluster",
                "EKSBastionAccessLambdaPermission"
            ]
        },
        "MLT": {
            "Type": "AWS::EC2::LaunchTemplate",
            "Properties": {
                "VersionDescription": "v1",
                "LaunchTemplateData": {
                    "IamInstanceProfile": {
                        "Name": "course-303-node-role"
                    },
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/sda1",
                            "Ebs": {
                                "DeleteOnTermination": true,
                                "Encrypted": false,
                                "VolumeSize": 50,
                                "VolumeType": "gp2"
                            }
                        }
                    ],
                    "NetworkInterfaces": [
                        {
                            "DeviceIndex": 0,
                            "AssociatePublicIpAddress": true,
                            "Groups": [
                                {
                                    "Ref": "DemoSG"
                                }
                            ],
                            "DeleteOnTermination": true
                        }
                    ],
                    "ImageId": {
                        "Fn::FindInMap": [
                            "ValueMap",
                            {
                                "Ref": "AWS::Region"
                            },
                            "AMI"
                        ]
                    },
                    "InstanceType": "c5.large",
                    "KeyName": {
                        "Fn::FindInMap": [
                            "ValueMap",
                            {
                                "Ref": "AWS::Region"
                            },
                            "key"
                        ]
                    },
                    "TagSpecifications": [
                        {
                            "ResourceType": "instance",
                            "Tags": [
                                {
                                    "Key": "Owner",
                                    "Value": {
                                        "Ref": "OwnerEmail"
                                    }
                                },
                                {
                                    "Key": "Name",
                                    "Value": "monitor"
                                }
                            ]
                        }
                    ],
                    "UserData": {
                        "Fn::Base64": {
                            "Fn::Join": [
                                "\n",
                                [
                                    {
                                        "Fn::FindInMap": [
                                            "ValueMap",
                                            {
                                                "Ref": "AWS::Region"
                                            },
                                            "ud"
                                        ]
                                    },
                                    {
                                        "Fn::Sub": "/usr/local/bin/cfn-signal -e 0 --stack ${AWS::StackName} --resource MG --region ${AWS::Region}\n"
                                    }
                                ]
                            ]
                        }
                    }
                }
            }
        },
        "MG": {
            "Type": "AWS::AutoScaling::AutoScalingGroup",
            "Properties": {
                "LaunchTemplate": {
                    "LaunchTemplateId": {
                        "Ref": "MLT"
                    },
                    "Version": {
                        "Fn::GetAtt": [
                            "MLT",
                            "LatestVersionNumber"
                        ]
                    }
                },
                "MaxSize": "1",
                "MinSize": "1",
                "DesiredCapacity": "1",
                "VPCZoneIdentifier": [
                    {
                        "Ref": "SN1"
                    }
                ],
                "Tags": [
                    {
                        "Key": "Owner",
                        "Value": {
                            "Ref": "OwnerEmail"
                        },
                        "PropagateAtLaunch": "true"
                    },
                    {
                        "Key": "trainer",
                        "Value": {
                            "Ref": "OwnerName"
                        },
                        "PropagateAtLaunch": "true"
                    }
                ]
            },
            "CreationPolicy": {
                "ResourceSignal": {
                    "Timeout": "PT20M",
                    "Count": 1
                }
            }
        }
    },
    "Outputs": {
        "EKSClusterName": {
            "Description": "EKS cluster name for TiDB",
            "Value": {
                "Fn::Sub": "${AWS::StackName}-eks"
            }
        },
        "LoadBalancerControllerRoleArn": {
            "Description": "IAM role ARN for AWS Load Balancer Controller (IRSA)",
            "Value": {
                "Fn::GetAtt": [
                    "LoadBalancerControllerRole",
                    "Arn"
                ]
            }
        },
        "LoadBalancerControllerRoleName": {
            "Description": "IAM role name for AWS Load Balancer Controller (IRSA)",
            "Value": {
                "Ref": "LoadBalancerControllerRole"
            }
        }
    }
}