AWSTemplateFormatVersion: 2010-09-09

Parameters:
  EC2InstanceType:
    Type: String
    Default: t2.micro
  ValidatorEC2InstanceType:
    Type: String
    Default: t2.micro
  RPCEC2InstanceType:
    Type: String
    Default: t2.micro
  BuildEC2InstanceType:
    Type: String
    Default: t2.micro
  EC2AMI:
    Type: String
    Default: 'ami-09e67e426f25ce0d7'
  DefaultAMI:
    Type: String
    Default: 'ami-09e67e426f25ce0d7'
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: 'AWS::EC2::KeyPair::KeyName'
    Default: 'joystream-key'
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  NumberOfValidators:
    Description: Number of validator instances to launch
    Type: Number
    Default: 2

Conditions:
  HasAMIId: !Not [!Equals [!Ref EC2AMI, ""]]

Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription:
        !Sub 'Internal Security group for validator nodes ${AWS::StackName}'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 30333
          ToPort: 30333
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}_validator'

  RPCSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription:
        !Sub 'Internal Security group for RPC nodes ${AWS::StackName}'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 9933
          ToPort: 9933
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 9944
          ToPort: 9944
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 30333
          ToPort: 30333
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}_rpc'

  InstanceLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            apt:
              wget: []
              unzip: []
    Properties:
      LaunchTemplateName: !Sub 'LaunchTemplate_${AWS::StackName}'
      LaunchTemplateData:
        ImageId: !If [HasAMIId, !Ref EC2AMI, !Ref DefaultAMI]
        InstanceType: !Ref EC2InstanceType
        KeyName: !Ref KeyName
        SecurityGroupIds:
          - !GetAtt SecurityGroup.GroupId
        BlockDeviceMappings:
          - DeviceName: /dev/sda1
            Ebs:
              VolumeSize: '40'
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash -xe

            # send script output to /tmp so we can debug boot failures
            exec > /tmp/userdata.log 2>&1

            # Update all packages
            apt-get update -y

            # Install the updates
            apt-get upgrade -y

            # Get latest cfn scripts and install them;
            apt-get install -y python3-setuptools
            mkdir -p /opt/aws/bin
            wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
            python3 -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-py3-latest.tar.gz

            /opt/aws/bin/cfn-signal -e $? -r "Instance Created" '${WaitHandle}'

  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      MinSize: '0'
      MaxSize: '10'
      DesiredCapacity: !Ref NumberOfValidators
      AvailabilityZones:
        Fn::GetAZs:
          Ref: "AWS::Region"
      MixedInstancesPolicy:
        LaunchTemplate:
          LaunchTemplateSpecification:
            LaunchTemplateId: !Ref InstanceLaunchTemplate
            Version: !GetAtt InstanceLaunchTemplate.LatestVersionNumber
          Overrides:
            - InstanceType: !Ref ValidatorEC2InstanceType
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}'
          PropagateAtLaunch: "true"

  RPCInstance:
    Type: AWS::EC2::Instance
    Properties:
      SecurityGroupIds:
        - !GetAtt RPCSecurityGroup.GroupId
      InstanceType: !Ref RPCEC2InstanceType
      LaunchTemplate:
        LaunchTemplateId: !Ref InstanceLaunchTemplate
        Version: !GetAtt InstanceLaunchTemplate.LatestVersionNumber
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}_rpc'

  BuildInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref BuildEC2InstanceType
      LaunchTemplate:
        LaunchTemplateId: !Ref InstanceLaunchTemplate
        Version: !GetAtt InstanceLaunchTemplate.LatestVersionNumber
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}_build'

  WaitHandle:
    Type: AWS::CloudFormation::WaitConditionHandle

  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    Properties:
      Handle: !Ref 'WaitHandle'
      Timeout: '600'
      Count: !Ref NumberOfValidators

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: PublicPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PublicReadForGetBucketObjects
            Effect: Allow
            Principal: '*'
            Action: 's3:GetObject'
            Resource: !Sub "arn:aws:s3:::${S3Bucket}/*"
      Bucket: !Ref S3Bucket

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
        - DomainName: !Select [1, !Split ["//", !GetAtt S3Bucket.WebsiteURL]]
          Id: pioneer-origin-s3
          CustomOriginConfig:
            OriginProtocolPolicy: http-only
        DefaultCacheBehavior:
          TargetOriginId: pioneer-origin-s3
          ViewerProtocolPolicy: redirect-to-https
          ForwardedValues:
            QueryString: true
        Enabled: true
        HttpVersion: http2

Outputs:
  AutoScalingId:
    Description: The Auto Scaling ID
    Value:  !Ref AutoScalingGroup
    Export:
      Name: !Sub "${AWS::StackName}AutoScalingGroup"

  RPCPublicIp:
    Description: The DNS name for the created instance
    Value:  !Sub "${RPCInstance.PublicIp}"
    Export:
      Name: !Sub "${AWS::StackName}RPCPublicIp"

  BuildPublicIp:
    Description: The DNS name for the created instance
    Value:  !Sub "${BuildInstance.PublicIp}"
    Export:
      Name: !Sub "${AWS::StackName}BuildPublicIp"

  S3BucketName:
    Value: !Ref S3Bucket
    Description: Name of S3 bucket to hold website content
    Export:
      Name: !Sub "${AWS::StackName}S3BucketName"

  DomainName:
    Description: CloudFront Domain Name
    Value:  !Sub "${CloudFrontDistribution.DomainName}"
    Export:
      Name: !Sub "${AWS::StackName}DomainName"
