AWSTemplateFormatVersion: '2010-09-09'
Description: lambda to replace the content-notifications-service
Parameters:
  Stack:
    Description: Stack name
    Type: String
    Default: content-api-mobile-notifications
  App:
    Description: Application name
    Type: String
    Default: mobile-notifications-content
  Stage:
    Description: Stage name
    Type: String
    AllowedValues:
      - CODE
      - PROD
    Default: CODE
  DeployBucket:
    Description: S3 Bucket where RiffRaff uploads artifacts on deploy
    Type: String
    Default: content-api-dist
  MobileAccountId:
    Description: Account ID of the gu moble account which
    Type: String
    Default: 201359054765
  CrossAccountBaseRoleName:
    Description: Base constituent name of the mobile account roles to assume
    Type: String
    Default: mobile-content-notifications-lambda-cross-account
  ConfigurationBucket:
    Description: S3 Bucket containing app configuration
    Type: String
    Default: mobile-notifications-dist
  KinesisStreamName:
    Description: Capi kinesis stream
    Type: String
    Default: content-api-firehose-v2
  BuildId:
    Description: Tag to be used for the image URL, e.g. riff raff build id
    Type: String
    Default: dev
  SharedResourcesStack:
    Description: Mobile notification content shared resources, e.g ecr repositories
    Type: String
    Default: mobile-notifications-shared-resources
Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      Path: /
      Policies:
        - PolicyName: assume-mobile-ssm-read-config-role
          PolicyDocument:
            Statement:
              Effect: Allow
              Action: sts:AssumeRole
              Resource: !Sub arn:aws:iam::${MobileAccountId}:role/${CrossAccountBaseRoleName}-ssm-${Stage}
        - PolicyName: assume-mobile-dynamo-role
          PolicyDocument:
            Statement:
              Effect: Allow
              Action: sts:AssumeRole
              Resource: !Sub arn:aws:iam::${MobileAccountId}:role/${CrossAccountBaseRoleName}-dynamo-${Stage}
        - PolicyName: logs
          PolicyDocument:
            Statement:
              Effect: Allow
              Action:
                - logs:CreateLogGroup
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource: "*"
        - PolicyName: invoke-lambda
          PolicyDocument:
            Statement:
              Effect: Allow
              Action:
                - lambda:InvokeFunction
              Resource: "*"
        - PolicyName: iam-read-and-assume
          PolicyDocument:
            Statement:
              Effect: Allow
              Action:
                - iam:PassRole
                - iam:GenerateCredentialReport
                - iam:Get*
                - iam:List*
              Resource: "*"
        - PolicyName: kinesis-read
          PolicyDocument:
             Statement:
               Effect: Allow
               Action:
                 - Kinesis:DescribeStream
                 - Kinesis:GetRecords
                 - Kinesis:GetShardIterator
                 - Kinesis:ListStream
               Resource: "*"
        - PolicyName: cloudwatch-put-metric-daata
          PolicyDocument:
             Statement:
               Effect: Allow
               Action:
                  - cloudwatch:PutMetricData
               Resource: "*"

  ContentLambdaV2:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub ${App}-${Stage}-v2
      PackageType: Image
      Code:
         ImageUri:
          Fn::Join:
            - ':'
            - - Fn::ImportValue: !Sub ${SharedResourcesStack}-ContentLambdaContainerRepositoryUri
              - !Ref BuildId
      Environment:
        Variables:
          CrossAccountSsmReadingRole: !Sub arn:aws:iam::${MobileAccountId}:role/${CrossAccountBaseRoleName}-ssm-${Stage}
          App: !Sub ${App}
          Stack: !Sub ${Stack}
          Stage: !Sub ${Stage}
      Description: Lambda to send notification when new content is published
      MemorySize: 4096
      Role: !GetAtt ExecutionRole.Arn
      Timeout: 60

  ContentEventV2Source:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      FunctionName: !Ref ContentLambdaV2
      Enabled: true
      EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${KinesisStreamName}-${Stage}
      StartingPosition: LATEST
      BisectBatchOnFunctionError: true

  contentLambdaErrorPercentageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      ActionsEnabled: true
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${MobileAccountId}:mobile-server-side
      AlarmName:
        Fn::Join:
          - '-'
          - - 'contentLambdaErrorPercentageAlarm'
            - !Ref Stage
      AlarmDescription:  'Triggers if mobile-notifications-content lambda does not execute successfully. Note: this lambda is hosted in the CAPI account. Impact - Users that are subscribed to tags or contributors on their mobile device may not be getting the latest updates'
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 1
      Metrics:
        - Expression: 100*m1/m2
          Id: expr_1
          Label:
            Fn::Join:
              - ""
              - - "Error % of "
                - Ref: ContentLambdaV2
        - Id: m1
          MetricStat:
            Metric:
              Dimensions:
                - Name: FunctionName
                  Value:
                    Ref: ContentLambdaV2
              MetricName: Errors
              Namespace: AWS/Lambda
            Period: 60
            Stat: Sum
          ReturnData: false
        - Id: m2
          MetricStat:
            Metric:
              Dimensions:
                - Name: FunctionName
                  Value:
                    Ref: ContentLambdaV2
              MetricName: Invocations
              Namespace: AWS/Lambda
            Period: 60
            Stat: Sum
          ReturnData: false
      OKActions:
        - !Sub arn:aws:sns:${AWS::Region}:${MobileAccountId}:mobile-server-side
      Threshold: 1
      TreatMissingData: notBreaching
    DependsOn: ContentLambdaV2

  LiveBlogLambdaV2:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub ${App}-liveblogs-${Stage}-v2
      PackageType: Image
      Code:
        ImageUri:
          Fn::Join:
            - ':'
            - - Fn::ImportValue: !Sub ${SharedResourcesStack}-LiveblogsLambdaContainerRepositoryUri
              - !Ref BuildId
      Environment:
        Variables:
          CrossAccountSsmReadingRole: !Sub arn:aws:iam::${MobileAccountId}:role/${CrossAccountBaseRoleName}-ssm-${Stage}
          App: !Sub ${App}
          Stack: !Sub ${Stack}
          Stage: !Sub ${Stage}
      Description: Lambda that sends push notifications when new key events are published on a liveblog
      MemorySize: 4096
      Role: !GetAtt ExecutionRole.Arn
      Timeout: 60

  LiveBlogEventSourceV2:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      FunctionName: !Ref LiveBlogLambdaV2
      Enabled: true
      EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${KinesisStreamName}-${Stage}
      StartingPosition: LATEST
      BisectBatchOnFunctionError: true

  liveBlogLambdaErrorPercentageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      ActionsEnabled: true
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${MobileAccountId}:mobile-server-side
      AlarmName:
        Fn::Join:
          - '-'
          - - 'liveblogLambdaErrorPercentageAlarm'
            - !Ref Stage
      AlarmDescription: 'Triggers if mobile-notifications-content-liveblogs lambda does not execute successfully. Note: this lambda is hosted in the CAPI account. Impact - Users that are subscribed to liveblog notifications may not be getting the latest updates'
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 1
      Metrics:
        - Expression: 100*m1/m2
          Id: expr_1
          Label:
            Fn::Join:
              - ""
              - - "Error % of "
                - Ref: LiveBlogLambdaV2
        - Id: m1
          MetricStat:
            Metric:
              Dimensions:
                - Name: FunctionName
                  Value:
                    Ref: LiveBlogLambdaV2
              MetricName: Errors
              Namespace: AWS/Lambda
            Period: 60
            Stat: Sum
          ReturnData: false
        - Id: m2
          MetricStat:
            Metric:
              Dimensions:
                - Name: FunctionName
                  Value:
                    Ref: LiveBlogLambdaV2
              MetricName: Invocations
              Namespace: AWS/Lambda
            Period: 60
            Stat: Sum
          ReturnData: false
      OKActions:
        - !Sub arn:aws:sns:${AWS::Region}:${MobileAccountId}:mobile-server-side
      Threshold: 1
      TreatMissingData: notBreaching
    DependsOn: LiveBlogLambdaV2
