Parameters:
  VpcCidrBlock:
    Type: String
    Description: The CIDR block to be used by the VPC
  PublicSubnetCidrBlock:
    Type: String
    Description: The CIDR block to be used by the public subnet
  AvailabilityZone1:
    Type: String
    Description: The first availability zone
  AvailabilityZone2:
    Type: String
    Description: The second availability zone
  NodesSubnet1CidrBlock:
    Type: String
    Description: The CIDR block to be used by the first subnet for EKS nodes
  NodesSubnet2CidrBlock:
    Type: String
    Description: The CIDR block to be used by the second subnet for EKS nodes
  EksClusterName:
    Type: String
    Default: ""
    Description: The name with which to create the EKS cluster (defaults to <stack-name>-eks-cluster if not provided).
  EksClusterRoleArn:
    Type: String
    Description: The ARN of the eksClusterRole.
  ClusterNodes:
    Type: Number
    Description: The number of nodes to place in the cluster
  ClusterNodeSize:
    Type: String
    Description: The type of nodes to place in the cluster
  NodeInstanceRoleArn:
    Type: String
    Description: The ARN of the NodeInstanceRole
  DatabaseAdminUsername:
    Type: String
    Default: ""
    Description: The database admin username if creating a new database
  DatabaseAdminPassword:
    Type: String
    Default: ""
    Description: The database admin password if creating a new database
    NoEcho: true
  DatabaseInstanceSize:
    Type: String
    Default: ""
    Description: The database instance size

Conditions:
  EksClusterNameProvided: !Not [!Equals [!Ref EksClusterName, ""]]
  CreateDB: !Not [!Equals [!Ref DatabaseAdminUsername, ""]]

Resources:
  VPC:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-vpc.yaml
      Parameters:
        CidrBlock: !Ref VpcCidrBlock

  InternetGateway:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-internetgateway.yaml
      Parameters:
        VpcId: !GetAtt VPC.Outputs.Id

  PublicRouteTable:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-routetable.yaml
      Parameters:
        VpcId: !GetAtt VPC.Outputs.Id

  InternetGatewayRoute:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-route-internetgateway.yaml
      Parameters:
        RouteTableId: !GetAtt PublicRouteTable.Outputs.Id
        InternetGatewayId: !GetAtt InternetGateway.Outputs.Id

  PublicSubnet:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-subnet.yaml
      Parameters:
        CidrBlock: !Ref PublicSubnetCidrBlock
        VpcId: !GetAtt VPC.Outputs.Id
        AvailabilityZone: !Ref AvailabilityZone1
        MapPublicIpOnLaunch: true
        RouteTableId: !GetAtt PublicRouteTable.Outputs.Id

  NatGateway:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-natgateway.yaml
      Parameters:
        SubnetId: !GetAtt PublicSubnet.Outputs.Id

  PrivateRouteTable:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-routetable.yaml
      Parameters:
        VpcId: !GetAtt VPC.Outputs.Id

  NatGatewayRoute:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-route-natgateway.yaml
      Parameters:
        RouteTableId: !GetAtt PrivateRouteTable.Outputs.Id
        NatGatewayId: !GetAtt NatGateway.Outputs.Id

  NodesSubnet1:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-subnet.yaml
      Parameters:
        CidrBlock: !Ref NodesSubnet1CidrBlock
        VpcId: !GetAtt VPC.Outputs.Id
        AvailabilityZone: !Ref AvailabilityZone1
        RouteTableId: !GetAtt PrivateRouteTable.Outputs.Id
        EksClusterName: !If
          - EksClusterNameProvided
          - !Ref EksClusterName
          - !Sub ${AWS::StackName}-eks-cluster

  NodesSubnet2:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-subnet.yaml
      Parameters:
        CidrBlock: !Ref NodesSubnet2CidrBlock
        VpcId: !GetAtt VPC.Outputs.Id
        AvailabilityZone: !Ref AvailabilityZone2
        RouteTableId: !GetAtt PrivateRouteTable.Outputs.Id
        EksClusterName: !If
          - EksClusterNameProvided
          - !Ref EksClusterName
          - !Sub ${AWS::StackName}-eks-cluster

  EfsFileSystem:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/efs-filesystem.yaml

  EfsMountTarget1a:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/efs-mounttarget.yaml
      Parameters:
        FileSystemId: !GetAtt EfsFileSystem.Outputs.Id
        SecurityGroupId: !GetAtt EfsSecurityGroup.Outputs.Id
        SubnetId: !GetAtt NodesSubnet1.Outputs.Id

  EfsMountTarget1b:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/efs-mounttarget.yaml
      Parameters:
        FileSystemId: !GetAtt EfsFileSystem.Outputs.Id
        SecurityGroupId: !GetAtt EfsSecurityGroup.Outputs.Id
        SubnetId: !GetAtt NodesSubnet2.Outputs.Id

  EksCluster:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/eks-cluster.yaml
      Parameters:
        Name: !If
          - EksClusterNameProvided
          - !Ref EksClusterName
          - !Sub ${AWS::StackName}-eks-cluster
        SubnetIds: !Join
          - ","
          - - !GetAtt NodesSubnet1.Outputs.Id
            - !GetAtt NodesSubnet2.Outputs.Id
        RoleArn: !Ref EksClusterRoleArn

  NodeGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/eks-nodegroup.yaml
      Parameters:
        ClusterName: !GetAtt EksCluster.Outputs.Id
        DiskSize: 30
        InstanceTypes: !Ref ClusterNodeSize
        DesiredSize: !Ref ClusterNodes
        SubnetIds: !Join
          - ","
          - - !GetAtt NodesSubnet1.Outputs.Id
            - !GetAtt NodesSubnet2.Outputs.Id
        RoleArn: !Ref NodeInstanceRoleArn

  ApplicationLogGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/logs-loggroup.yaml
      Parameters:
        LogGroupId: !GetAtt EksCluster.Outputs.Id
        LogGroupSuffix: application

  DataplaneLogGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/logs-loggroup.yaml
      Parameters:
        LogGroupId: !GetAtt EksCluster.Outputs.Id
        LogGroupSuffix: dataplane

  HostLogGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/logs-loggroup.yaml
      Parameters:
        LogGroupId: !GetAtt EksCluster.Outputs.Id
        LogGroupSuffix: host

  PerformanceLogGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/logs-loggroup.yaml
      Parameters:
        LogGroupId: !GetAtt EksCluster.Outputs.Id
        LogGroupSuffix: performance

  HttpSecurityGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroup.yaml
      Parameters:
        Description: !Sub ${AWS::StackName}-http-security-group
        VpcId: !GetAtt VPC.Outputs.Id

  HttpSecurityGroupIngress80:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroupingress.yaml
      Parameters:
        SecurityGroupId: !GetAtt HttpSecurityGroup.Outputs.Id
        CidrIp: 0.0.0.0/0
        FromPort: 80
        ToPort: 80

  HttpSecurityGroupIngress443:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroupingress.yaml
      Parameters:
        SecurityGroupId: !GetAtt HttpSecurityGroup.Outputs.Id
        CidrIp: 0.0.0.0/0
        FromPort: 443
        ToPort: 443

  EfsSecurityGroup:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroup.yaml
      Parameters:
        Description: !Sub ${AWS::StackName}-efs-security-group
        VpcId: !GetAtt VPC.Outputs.Id

  EfsSecurityGroupIngress2049:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroupingress.yaml
      Parameters:
        SecurityGroupId: !GetAtt EfsSecurityGroup.Outputs.Id
        SourceSecurityGroupId: !GetAtt EksCluster.Outputs.SecurityGroupId
        FromPort: 2049
        ToPort: 2049

  DatabaseSubnetGroup:
    Condition: CreateDB
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/rds-subnet-group.yaml
      Parameters:
        SubnetId1: !GetAtt NodesSubnet1.Outputs.Id
        SubnetId2: !GetAtt NodesSubnet2.Outputs.Id

  DatabaseSecurityGroup:
    Condition: CreateDB
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroup.yaml
      Parameters:
        VpcId: !GetAtt VPC.Outputs.Id
        Description: !Sub ${AWS::StackName}-rds-security-group

  Database:
    Condition: CreateDB
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/rds-db-instance.yaml
      Parameters:
        SubnetGroup: !GetAtt DatabaseSubnetGroup.Outputs.Name
        SecurityGroup: !GetAtt DatabaseSecurityGroup.Outputs.Id
        DatabaseAdminUsername: !Ref DatabaseAdminUsername
        DatabaseAdminPassword: !Ref DatabaseAdminPassword
        DatabaseInstanceSize: !Ref DatabaseInstanceSize

  DatabaseSecurityGroupIngress5432:
    Condition: CreateDB
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://bsee-cloud-trial.s3-eu-west-1.amazonaws.com/2021.3.1-6427/ec2-securitygroupingress.yaml
      Parameters:
        SourceSecurityGroupId: !GetAtt EksCluster.Outputs.SecurityGroupId
        SecurityGroupId: !GetAtt DatabaseSecurityGroup.Outputs.Id
        FromPort: !GetAtt Database.Outputs.DatabasePort
        ToPort: !GetAtt Database.Outputs.DatabasePort

Outputs:
  EksClusterName:
    Description: The EKS Cluster Name
    Value: !GetAtt EksCluster.Outputs.Id
  EksClusterSecurityGroupId:
    Description: The EKS Cluster security group id
    Value: !GetAtt EksCluster.Outputs.SecurityGroupId
  EfsFileSystemId:
    Description: The id of the EFS file system
    Value: !GetAtt EfsFileSystem.Outputs.Id
  HttpSecurityGroupId:
    Description: The Id for the HttpSecurityGroup for the load balancer created by the ingress controller
    Value: !GetAtt HttpSecurityGroup.Outputs.Id
  NodesSubnet1Id:
    Description: The ID of the first subnet for the EKS cluster nodes
    Value: !GetAtt NodesSubnet1.Outputs.Id
  NodesSubnet2Id:
    Description: The ID of the second subnet for the EKS cluster nodes
    Value: !GetAtt NodesSubnet2.Outputs.Id
  DatabaseEndpoint:
    Description: The endpoint of the database
    Condition: CreateDB
    Value: !GetAtt Database.Outputs.DatabaseEndpoint
  DatabaseSecurityGroupId:
    Description: The Database security group id
    Condition: CreateDB
    Value: !GetAtt DatabaseSecurityGroup.Outputs.Id