AWSTemplateFormatVersion: "2010-09-09"
Description: Reads the product catalog from Zuora and stores it in S3

Parameters:
    Stage:
        Description: Stage name
        Type: String
        AllowedValues:
            - CODE
            - PROD
        Default: CODE

Mappings:
    StageVariables:
        CODE:
            ReadableS3Buckets:
              - arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/CODE/zuoraRest-CODE.*.json
            WriteableS3Buckets:
              - arn:aws:s3:::gu-zuora-catalog/CODE/*
        PROD:
            ReadableS3Buckets:
              - arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/CODE/zuoraRest-CODE.*.json
              - arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/PROD/zuoraRest-PROD.*.json
            WriteableS3Buckets:
              - arn:aws:s3:::gu-zuora-catalog/PROD/*

Conditions:
    CreateProdOnlyResources: !Equals [ !Ref Stage, PROD ]

Resources:
    CatalogServiceRole:
        Type: AWS::IAM::Role
        Properties:
            AssumeRolePolicyDocument:
                Statement:
                    - Effect: Allow
                      Principal:
                          Service:
                             - lambda.amazonaws.com
                      Action:
                          - sts:AssumeRole
            Path: /
            Policies:
                - PolicyName: LambdaPolicy
                  PolicyDocument:
                      Statement:
                          - Effect: Allow
                            Action:
                            - logs:CreateLogGroup
                            - logs:CreateLogStream
                            - logs:PutLogEvents
                            - lambda:InvokeFunction
                            Resource:
                            - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/catalog-service-zuora-code-${Stage}:log-stream:*
                            - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/catalog-service-zuora-prod-${Stage}:log-stream:*

                - PolicyName: ReadPrivateCredentials
                  PolicyDocument:
                      Statement:
                          - Effect: Allow
                            Action: s3:GetObject
                            Resource: !FindInMap [StageVariables, !Ref Stage, ReadableS3Buckets]
                          - Effect: Allow
                            Action: s3:PutObject
                            Resource: !FindInMap [StageVariables, !Ref Stage, WriteableS3Buckets]

    CODECatalogServiceLambda:
        Type: AWS::Lambda::Function
        Properties:
            Description: Reads the product catalog from CODE Zuora and stores it in S3
            FunctionName:
                !Sub catalog-service-zuora-code-${Stage}
            Code:
                S3Bucket: subscriptions-dist
                S3Key: !Sub subscriptions/${Stage}/catalog-service/catalog-service.jar
            Handler: com.gu.catalogService.Handler::apply
            Environment:
                Variables:
                  Stage: !Ref Stage
                  ZuoraEnvironment: CODE
            Role:
                !GetAtt CatalogServiceRole.Arn
            MemorySize: 1536
            Runtime: java21
            Timeout: 300
            Architectures:
              - arm64
        DependsOn:
        - CatalogServiceRole

    CODECatalogServiceLambdaInvokePermission:
        Type: AWS::Lambda::Permission
        Properties:
            Action: lambda:invokeFunction
            FunctionName: !Ref CODECatalogServiceLambda
            Principal: events.amazonaws.com
            SourceArn: !GetAtt CatalogServiceScheduler.Arn
        DependsOn:
        - CODECatalogServiceLambda
        - CatalogServiceScheduler

    CatalogServiceScheduler:
        Type: "AWS::Events::Rule"
        Properties:
            Description: Triggers the CODE Catalog Service Lambda on a schedule
            Name: !Sub catalog-service-scheduler-zuora-code-${Stage}
            ScheduleExpression: rate(10 minutes) #https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html#RateExpressions
            Targets:
            - Arn: !GetAtt CODECatalogServiceLambda.Arn
              Id: !Ref CODECatalogServiceLambda
        DependsOn:
        - CODECatalogServiceLambda

    CatalogS3Bucket:
        Type: "AWS::S3::Bucket"
        Condition: CreateProdOnlyResources
        Properties:
            AccessControl: Private
            BucketName: gu-zuora-catalog
            VersioningConfiguration:
              Status: Enabled
        DeletionPolicy: Retain

    PRODCatalogServiceLambda:
        Type: AWS::Lambda::Function
        Properties:
            Description: Reads the product catalog from PROD Zuora and stores it in S3
            FunctionName:
                !Sub catalog-service-zuora-prod-${Stage}
            Code:
                S3Bucket: subscriptions-dist
                S3Key: !Sub subscriptions/${Stage}/catalog-service/catalog-service.jar
            Handler: com.gu.catalogService.Handler::apply
            Environment:
                Variables:
                  Stage: !Ref Stage
                  ZuoraEnvironment: PROD
            Role:
                !GetAtt CatalogServiceRole.Arn
            MemorySize: 1536
            Runtime: java21
            Timeout: 300
            Architectures:
              - arm64
        DependsOn:
        - CatalogServiceRole

    PRODCatalogServiceLambdaInvokePermission:
        Type: AWS::Lambda::Permission
        Condition: CreateProdOnlyResources
        Properties:
            Action: lambda:invokeFunction
            FunctionName: !Ref PRODCatalogServiceLambda
            Principal: events.amazonaws.com
            SourceArn: !GetAtt ProdCatalogServiceScheduler.Arn
        DependsOn:
        - PRODCatalogServiceLambda
        - ProdCatalogServiceScheduler

    ProdCatalogServiceScheduler:
        Type: "AWS::Events::Rule"
        Condition: CreateProdOnlyResources
        Properties:
            Description: Triggers the PROD Catalog Service Lambda on a schedule
            Name: !Sub catalog-service-scheduler-zuora-prod-${Stage}
            ScheduleExpression: rate(10 minutes) #https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html#RateExpressions
            Targets:
            - Arn: !GetAtt PRODCatalogServiceLambda.Arn
              Id: !Sub PRODCatalogServiceLambda
        DependsOn:
        - PRODCatalogServiceLambda

    StaleProdCatalogAlarm:
      Type: AWS::CloudWatch::Alarm
      Condition: CreateProdOnlyResources
      Properties:
        AlarmActions:
          - Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
        AlarmName: High error rate when fetching PROD Zuora Catalog
        ComparisonOperator: GreaterThanOrEqualToThreshold
        Dimensions:
          - Name: FunctionName
            Value: !Ref PRODCatalogServiceLambda
        EvaluationPeriods: 18
        MetricName: Errors
        Namespace: AWS/Lambda
        Period: 300
        Statistic: Sum
        Threshold: 1
        TreatMissingData: notBreaching

    StaleCodeCatalogAlarm:
      Type: AWS::CloudWatch::Alarm
      Condition: CreateProdOnlyResources
      Properties:
        AlarmActions:
          - Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
        AlarmName: High error rate when fetching CODE Zuora Catalog
        ComparisonOperator: GreaterThanOrEqualToThreshold
        Dimensions:
          - Name: FunctionName
            Value: !Ref CODECatalogServiceLambda
        EvaluationPeriods: 18
        MetricName: Errors
        Namespace: AWS/Lambda
        Period: 300
        Statistic: Sum
        Threshold: 1
        TreatMissingData: notBreaching

