AWSTemplateFormatVersion: 2010-09-09
Description: 'RI and SP Migration'
Parameters:
  S3BucketName:
    Type: String
    Description: S3 bucket name for Lambda zip file
    Default: 'awslabs-code-us-east-1'
  LambdaZipFile:
    Type: String
    Description: S3 key for Lambda zip file
    Default: 'ReservedInstancesMigration/lambda.zip'
  DynamoTableName:
    Type: String
    Description: DynamoDB table name
    Default: 'ri-sp-migration'
  EventInterval:
    Type: Number
    Description: Interval (hours) between two account status checkes
    Default: 1
  EventRuleName:
    Type: String
    Description: Rule name for defining the interval
    Default: 'ri-sp-migration'     
  OrganizationsEndpoint:
    Type: String
    Description: AWS Organizations service endpoint. Refer to https://docs.aws.amazon.com/general/latest/gr/ao.html
    Default: 'organizations.us-east-1.amazonaws.com'
  CostExplorerEndpoint:
    Type: String
    Description: AWS Cost Explorer service endpoint. Refer to https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/Welcome.html
    Default: 'ce.us-east-1.amazonaws.com'
  SupportEndpoint:
    Type: String
    Description: AWS Support service endpoint. Refer to https://docs.aws.amazon.com/awssupport/latest/user/Welcome.html
    Default: 'support.us-east-1.amazonaws.com'    
  ActionType:
    Type: String
    AllowedValues:
      - 'SUPPORT_CASE_AND_EMAIL'
      - 'EMAIL_ONLY'
      - 'SUPPORT_CASE_ONLY'
    Default: 'SUPPORT_CASE_AND_EMAIL'    
    Description: Specify an action for the solution.   
  EmailAddress:
    Type: String
    Description: Email address for support case notification
    AllowedPattern: '.+@.+'
  SNSTopicName:
    Type: String
    Description: SNS topic name for support case notification
    Default: 'ri-sp-migration'    
Conditions:
  IsSinglar: !Equals [ !Ref EventInterval, 1 ]    
Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName:
        Ref: SNSTopicName
      TopicName:
        Ref: SNSTopicName
  SNSTopicEmailSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: email
      TopicArn:
        Ref: SNSTopic
      Endpoint: !Ref EmailAddress
    DependsOn:
      - SNSTopic     
  DynamoTable:
    Type: AWS::DynamoDB::Table
    Properties:
      KeySchema:
        - AttributeName: Organization
          KeyType: HASH
      AttributeDefinitions:
        - AttributeName: Organization
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES
      TableName: 
        Ref: DynamoTableName
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  RefreshHandlerServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  RefreshHandlerServiceRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - dynamodb:UpdateItem
              - organizations:ListAccounts
            Effect: Allow
            Resource: "*"
        Version: "2012-10-17"
      PolicyName: RefreshHandlerServiceRoleDefaultPolicy
      Roles:
        - Ref: RefreshHandlerServiceRole              
  RefreshHandlerLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          Ref: S3BucketName
        S3Key:
          Ref: LambdaZipFile
      Handler: refresh.handler
      Role:
        Fn::GetAtt:
          - RefreshHandlerServiceRole
          - Arn
      Runtime: nodejs12.x
      Environment:
        Variables:
          TABLE_NAME:
            Ref: DynamoTable
          ORGANIZATIONS_ENDPOINT:
            Ref: OrganizationsEndpoint
    DependsOn:
      - RefreshHandlerServiceRoleDefaultPolicy 
      - RefreshHandlerServiceRole
      - DynamoTable
  RefreshHandlerAllowEventRuleStackAccountStatusRefresh:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
          - RefreshHandlerLambdaFunction
          - Arn
      Principal: events.amazonaws.com
      SourceArn:
        Fn::GetAtt:
          - AccountStatusRefreshEventRule
          - Arn
    DependsOn:
      - AccountStatusRefreshEventRule
      - RefreshHandlerLambdaFunction
  ProcessHandlerServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/service-role/AWSLambdaDynamoDBExecutionRole
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/job-function/Billing
  ProcessHandlerServiceRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - ce:GetReservationUtilization
              - ce:GetSavingsPlansUtilizationDetails
              - sns:Publish
              - support:CreateCase
              - support:DescribeCases
            Effect: Allow
            Resource: "*"
        Version: "2012-10-17"
      PolicyName: ProcessHandlerServiceRoleDefaultPolicy
      Roles:
        - Ref: ProcessHandlerServiceRole
    DependsOn:
      - ProcessHandlerServiceRole        
  ProcessHandlerLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          Ref: S3BucketName
        S3Key:
          Ref: LambdaZipFile
      Handler: process.handler
      Role:
        Fn::GetAtt:
          - ProcessHandlerServiceRole
          - Arn
      Runtime: nodejs12.x
      Environment:
        Variables:
          EMAIL_ADDRESS:
            Ref: EmailAddress
          ACTION_TYPE:
            Ref: ActionType
          TOPIC_ARN:
            Ref: SNSTopic
          COST_EXPLORER_ENDPOINT:
            Ref: CostExplorerEndpoint
          SUPPORT_ENDPOINT:
            Ref: SupportEndpoint            
    DependsOn:
      - ProcessHandlerServiceRoleDefaultPolicy
      - ProcessHandlerServiceRole
      - SNSTopic
  ProcessHandlerDynamoDBEventSource:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      EventSourceArn:
        Fn::GetAtt:
          - DynamoTable
          - StreamArn
      FunctionName:
        Ref: ProcessHandlerLambdaFunction
      BatchSize: 1
      BisectBatchOnFunctionError: false
      MaximumRetryAttempts: 10
      StartingPosition: TRIM_HORIZON
    DependsOn:
      - DynamoTable
      - ProcessHandlerLambdaFunction      
  AccountStatusRefreshEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Ref EventRuleName
      ScheduleExpression: !Join ['',[rate(,!Join [' ',[!Ref EventInterval,!If [IsSinglar, hour, hours]]],)]]   
      State: ENABLED
      Targets:
        - Arn:
            Fn::GetAtt:
              - RefreshHandlerLambdaFunction
              - Arn
          Id: Target0
    DependsOn:
      - RefreshHandlerLambdaFunction         