Description: >
  This template deploys an ECS cluster to the provided VPC and subnets
  using an Auto Scaling Group

Parameters:

  EnvironmentName:
    Description: An environment name that will be prefixed to resource names
    Type: String

  InstanceType:
    Description: Which instance type should we use to build the ECS cluster?
    Type: String
    Default: c4.large

  KeyName:
    Description: The EC2 Key Pair to allow SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
  
  ECSServiceLogGroupRetentionInDays:
    Type: Number
    Default: 30

  ECSServicesDomain:
    Type: String
    Description: "Domain name registerd under Route-53 that will be used for Service Discovery"

  EC2Ami:
    Description: EC2 AMI ID
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"

Resources:

  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Ref EnvironmentName

  ECSInstancesSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupDescription: "Security group for the instances"
      VpcId:
        'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
      SecurityGroupIngress:
        - CidrIp:
            'Fn::ImportValue': !Sub "${EnvironmentName}:VpcCIDR"
          IpProtocol: -1

  ECSServiceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupDescription: "Security group for the service"
      VpcId:
        'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
      SecurityGroupIngress:
        - CidrIp:
            'Fn::ImportValue': !Sub "${EnvironmentName}:VpcCIDR"
          IpProtocol: -1

  TaskIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchFullAccess
        - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
        - arn:aws:iam::aws:policy/AWSAppMeshPreviewEnvoyAccess
        - arn:aws:iam::aws:policy/AWSAppMeshEnvoyAccess
        - arn:aws:iam::aws:policy/SecretsManagerReadWrite

  TaskExecutionIamRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument: |
        {
            "Statement": [{
                "Effect": "Allow",
                "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]},
                "Action": [ "sts:AssumeRole" ]
            }]
        }
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess

  ECSServiceLogGroup:
    Type: 'AWS::Logs::LogGroup'
    Properties:
      RetentionInDays:
        Ref: ECSServiceLogGroupRetentionInDays

  ECSServiceDiscoveryNamespace:
    Type: AWS::ServiceDiscovery::PrivateDnsNamespace
    Properties:
      Vpc:
        'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
      Name: { Ref: ECSServicesDomain }

  BastionSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow http to client host
      VpcId: 
        'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0

  BastionHost:
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: !Ref EC2Ami
      KeyName: !Ref KeyName
      InstanceType: t2.micro
      SecurityGroupIds:
      - !Ref BastionSecurityGroup
      SubnetId: 
        'Fn::ImportValue': !Sub "${EnvironmentName}:PublicSubnet1"
      Tags: 
        - Key: Name
          Value: bastion-host

Outputs:

  Cluster:
    Description: A reference to the ECS cluster
    Value: !Ref ECSCluster
    Export:
      Name: !Sub "${EnvironmentName}:ECSCluster"

  ECSServiceDiscoveryNamespace:
    Description: A SDS namespace that will be used by all services in this cluster
    Value: !Ref ECSServiceDiscoveryNamespace
    Export:
      Name: !Sub "${EnvironmentName}:ECSServiceDiscoveryNamespace"

  ECSServiceLogGroup:
    Description: Log group for services to publish logs
    Value: !Ref ECSServiceLogGroup
    Export:
      Name: !Sub "${EnvironmentName}:ECSServiceLogGroup"

  ECSServiceSecurityGroup:
    Description: Security group to be used by all services in the cluster
    Value: !Ref ECSServiceSecurityGroup
    Export:
      Name: !Sub "${EnvironmentName}:ECSServiceSecurityGroup"

  TaskExecutionIamRoleArn:
    Description: Task Executin IAM role used by ECS tasks
    Value: { "Fn::GetAtt": TaskExecutionIamRole.Arn }
    Export:
      Name: !Sub "${EnvironmentName}:TaskExecutionIamRoleArn"

  TaskIamRoleArn:
    Description: IAM role to be used by ECS task
    Value: { "Fn::GetAtt": TaskIamRole.Arn }
    Export:
      Name: !Sub "${EnvironmentName}:TaskIamRoleArn"

  BastionIP:
    Description: Public IP for ssh access to bastion host
    Value:
      'Fn::GetAtt': [ BastionHost, PublicIp ]