# Copyright 2022 Amazon.com and its affiliates; all rights reserved. 
# This file is Amazon Web Services Content and may not be duplicated or distributed without permission.
AWSTemplateFormatVersion: "2010-09-09"
Description: Serverless Analytics workshop studio

Parameters:
  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

  EnvironmentName:
      Description: An environment name that is prefixed to resource names
      Type: String
      Default: ServerlessAnalytics
      MinLength: 2
      MaxLength: 20
      AllowedPattern: ([a-zA-Z0-9]+)

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: "10.1.0.0/16"
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} VPC

  InternetGateway:
    Type: AWS::EC2::InternetGateway
     
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: "10.1.1.0/24"
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Public Subnet (AZ1)

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: "10.1.2.0/24"
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Public Subnet (AZ2)

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs  '' ]
      CidrBlock: "10.1.11.0/24"
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Private Subnet (AZ1)

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 1, !GetAZs  '' ]
      CidrBlock: "10.1.12.0/24"
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Private Subnet (AZ2)

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Public Routes

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2


  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName} Private Routes

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet1

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet2

  PublicSubnetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${EnvironmentName}-public-subnet-sg
      GroupDescription: "Security group with all ports open rule"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 0.0.0.0/0
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0  

  PrivateSubnetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${EnvironmentName}-private-subnet-sg
      GroupDescription: "Security group for private subnets"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: -1
          CidrIp: "10.1.0.0/16"
  ServerlessAnalyticsRole:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      RoleName: "ServerlessAnalyticsRole"
      AssumeRolePolicyDocument: '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"glue.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
      MaxSessionDuration: 43200
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AWSGlueConsoleFullAccess"
        - "arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole"
        - "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        - "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
        - "arn:aws:iam::aws:policy/AmazonAthenaFullAccess"
      Description: "Allows Glue crawler to access S3 buckets"
  
  EC2Role:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      RoleName: "ServerlessAnalyticsEC2Role"
      AssumeRolePolicyDocument: '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
      MaxSessionDuration: 43200
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        - "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
      Description: "Allows EC2 to copy data from nyc-data s3 bucket into Raw bucket"

  EC2InstanceProfile: 
    Type: AWS::IAM::InstanceProfile
    Properties: 
      InstanceProfileName: 'EC2InstanceProfile'
      Path: '/'
      Roles: 
        - !Ref EC2Role

  RawS3Bucket:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Delete
    Properties:
      BucketName: !Join ['-', ["serverlessanalytics", !Ref AWS::AccountId, "raw"]]
  
  TransformedS3Bucket:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Delete
    Properties:
      BucketName: !Join ['-', ["serverlessanalytics", !Ref AWS::AccountId, "transformed"]]
  
  AthenaS3Bucket:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Delete
    Properties:
      BucketName: !Join ['-', ["serverlessanalytics", !Ref AWS::AccountId, "athena"]]

  AnalyticsEC2Instance:
    Type: AWS::EC2::Instance
    DependsOn: RawS3Bucket
    Properties:
      InstanceType: t3a.medium
      IamInstanceProfile: !Ref EC2InstanceProfile
      ImageId: !Ref  LatestAmiId
      SubnetId: !Ref PublicSubnet1
      SecurityGroupIds:
        - !Ref PublicSubnetSecurityGroup
      # KeyName: !Ref EC2KeyPair
      BlockDeviceMappings: 
      - DeviceName: "/dev/xvda"
        Ebs: 
          VolumeType: "gp2"
          VolumeSize: "50"
      UserData:
        'Fn::Base64': 
          !Sub 
            - |
              #!/bin/bash -x
              echo "Script starts at: `date`"

              aws s3 cp s3://ws-assets-prod-iad-r-pdx-f3b3f9f1a7d6a3d0/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-01.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-pdx-f3b3f9f1a7d6a3d0/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-02.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-pdx-f3b3f9f1a7d6a3d0/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-03.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-sfo-f61fc67057535f1b/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-04.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-lhr-cc4472a651221311/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-05.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-lhr-cc4472a651221311/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-06.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              aws s3 cp s3://ws-assets-prod-iad-r-sfo-f61fc67057535f1b/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-08.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/ 
              aws s3 cp s3://ws-assets-prod-iad-r-sfo-f61fc67057535f1b/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-10.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/ 
              aws s3 cp s3://ws-assets-prod-iad-r-sfo-f61fc67057535f1b/276faf92-bffc-4843-8a8e-8078add48194/yellow-tripdata/yellow_tripdata_2020-12.csv s3://${RAWBUCKETNAME}/nyc-taxi/yellow-tripdata/
              
              aws s3 cp s3://ws-assets-prod-iad-r-sfo-f61fc67057535f1b/276faf92-bffc-4843-8a8e-8078add48194/taxi_zone_lookup.csv s3://${RAWBUCKETNAME}/nyc-taxi/taxi_zone_lookup/taxi_zone_lookup.csv

              /opt/aws/bin/cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource WaitCondition
              echo "Script ends at: `date`"
            - RAWBUCKETNAME: !Ref RawS3Bucket
              
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2-ServerlessAnalytics-Client

  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    CreationPolicy:
      ResourceSignal: 
        Timeout: PT1H

Outputs:
  GlueIAMRole:
    Description: "IAM Role for Glue"
    Value: "ServerlessAnalyticsRole"
  RawBucketPath:
    Value: !Join ['', ["s3://", !Ref RawS3Bucket]]
  TransformedBucketPath:
    Value: !Join ['', ["s3://", !Ref TransformedS3Bucket]]
  AthenaBucketPath:
    Value: !Join ['', ["s3://", !Ref AthenaS3Bucket]]

