Parameters:
  KeyName:
    Description: SSH key pair to use for instance login
    Type: AWS::EC2::KeyPair::KeyName
  AcceptRStudioLicenseAndInstall:
    Description: This CFN template installs RStudio Server to an EC2 instance. Please review and accept the AGPL v3 license http://www.gnu.org/licenses/agpl-3.0-standalone.html. 
    Type: String
    Default: Deny
    AllowedValues:
      - Accept
      - Deny

Conditions:
  ShouldCreateInstance:
    !Equals [Accept, !Ref AcceptRStudioLicenseAndInstall]
  DenyInstallation:
    !Equals [Deny, !Ref AcceptRStudioLicenseAndInstall]

#mappings between regions and amis to launch
# instance: Ubuntu Server 20.04 LTS (HVM), SSD Volume Type 64-bit x86
Mappings:
  Region:
    us-east-1:
      HostAmi: ami-0885b1f6bd170450c
    us-east-2:
      HostAmi: ami-0a91cd140a1fc148a
    us-west-2:
      HostAmi: ami-06e54d05255faf8f6
    eu-west-1:
      HostAmi: ami-0aef57767f5404a3c

Resources:
  VPC:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: RStudio SageMaker VPC
        - Key: CreatedFor
          Value: ML blog

  VPCEndpoint:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::VPCEndpoint
    Properties:
      RouteTableIds:
        - !Ref PublicRouteTable
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      VpcId: !Ref VPC

  InternetGateway:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: RStudio SageMaker Internet Gateway
        - Key: CreatedFor
          Value: ML blog

  AttachGateway:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone: !Select
        - '0'
        - !GetAZs ''
      Tags:
        - Key: Name
          Value: RStudio SageMaker Public Subnet
        - Key: CreatedFor
          Value: ML blog

  PublicRouteTable:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: RStudio SageMaker Public Route Table
        - Key: CreatedFor
          Value: ML blog

  PublicRoute:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  Instance:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::Instance
    CreationPolicy:
      ResourceSignal:
        Count: '1'
        Timeout: PT30M
    Properties:
      KeyName: !Ref KeyName
      InstanceType: t3.xlarge 
      ImageId: !FindInMap [Region, !Ref "AWS::Region", HostAmi]
      IamInstanceProfile: !Ref InstanceProfile
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - Ref: PublicSubnetSecurityGroup
      Tags:
        - Key: Name
          Value: RStudio Server
        - Key: CreatedFor
          Value: ML blog
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          usermod --password $(openssl passwd -1 rstudio7862) ubuntu
          mkdir ~/Downloads/

          wget -P ~/Downloads/ https://bootstrap.pypa.io/get-pip.py
          ln -sv /usr/bin/python3 /usr/bin/python
          python ~/Downloads/get-pip.py
          pip install sagemaker boto3 pandas

          wget -P ~/Downloads/ https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
          pip install ~/Downloads/aws-cfn-bootstrap-py3-latest.tar.gz

          echo "deb https://cloud.r-project.org/bin/linux/ubuntu focal-cran40/" >> /etc/apt/sources.list
          apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
          apt-get update
          apt-get install -y tzdata 
          apt-get install -y wget r-base r-base-dev apt-transport-https ca-certificates gdebi-core curl \
                             gnupg-agent software-properties-common apt-transport-https libcurl4-openssl-dev 
          R -e "install.packages(c('reticulate', 'readr', 'curl', 'ggplot2', 'dplyr', 'stringr'), repos = 'http://cran.rstudio.com')"
          # R -e "library('reticulate');use_python('/usr/bin/python');"
          # export RETICULATE_PYTHON=/usr/bin/python
          R --version >> ~/R_VERSION_INSTALLED

          curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
          add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
          apt-get update
          apt-get install -y docker-ce docker-ce-cli containerd.io
          # groupadd docker
          usermod -aG docker ubuntu
          
          wget -P ~/Downloads/ https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip
          unzip ~/Downloads/awscli-exe-linux-x86_64.zip -d ~/Downloads/
          ~/Downloads/aws/install

          wget -P ~/Downloads/ https://download2.rstudio.org/server/bionic/amd64/rstudio-server-1.3.1093-amd64.deb
          gdebi -n ~/Downloads/rstudio-server-1.3.1093-amd64.deb
          cfn-signal -e $? --stack ${AWS::StackName} --resource Instance --region ${AWS::Region} # check 1

          su - ubuntu -c "mkdir /home/ubuntu/.aws/"
          su - ubuntu -c "echo [default] >> /home/ubuntu/.aws/config"
          su - ubuntu -c "echo region = ${AWS::Region} >> /home/ubuntu/.aws/config"
          su - ubuntu -c "echo export RETICULATE_PYTHON=/usr/bin/python >> /home/ubuntu/.bashrc"

          echo "Success" >> ~/EC2_INIT_COMPLETED

  PublicSubnetSecurityGroup:
    Condition: ShouldCreateInstance
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: rstudio-sagemaker-sg
      GroupDescription: RStudio SageMaker Instance Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          FromPort: '22'
          IpProtocol: tcp
          ToPort: '22'
        - CidrIp: 0.0.0.0/0
          FromPort: '8787'
          IpProtocol: tcp
          ToPort: '8787'
      Tags:
        - Key: CreatedFor
          Value: ML blog

  EC2SageMakerRole:
    Condition: ShouldCreateInstance
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
                - sagemaker.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/IAMReadOnlyAccess
        - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
      Tags:
        - Key: CreatedFor
          Value: ML blog

  InstanceProfile:
    Condition: ShouldCreateInstance
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - Ref: EC2SageMakerRole

Outputs:
  RStudio:
    Condition: ShouldCreateInstance
    Description: RStudio SSH command
    Value: !Sub "ssh -L 8787:localhost:8787 -i ${KeyName}.pem ubuntu@${Instance.PublicDnsName}"
  
  RStudioURL:
    Condition: ShouldCreateInstance
    Description: RStudio public URL
    Value: !Sub "${Instance.PublicDnsName}:8787"

  RStudioAGPLv3Licence:
    Condition: DenyInstallation
    Description: This CFN template installs RStudio Server to an EC2 instance. Please restart the stack creation process, review and accept the AGPL v3 license http://www.gnu.org/licenses/agpl-3.0-standalone.html.
    Value: "Denied"