service: frontend-api

plugins:
  - serverless-layers
  - serverless-plugin-conditional-functions

custom:
  apiName: ${{self:service}}-${{self:provider.stage}}
  userPoolName: ${{self:service}}-${{ self:custom.stage_map.${{self:provider.stage}} }}-user-pool
  stripeSecret:
    devel: stripe-test
    test: stripe-test
    live: stripe-live
  appSyncAPI:
    devel: arn:aws:appsync:eu-west-1:776891437216:apis/vdfpimr7jrakjlmqvg4dd7zfz4
    devel2: arn:aws:appsync:eu-west-1:776891437216:apis/cuia77aa4vfwffsbxa577sn33e
    devel3: arn:aws:appsync:eu-west-1:776891437216:apis/tago7uraojguxoto5ovbud552m
    live: arn:aws:appsync:eu-west-1:776891437216:apis/kwjkicpkffbrfie5rt7ljpanvi
    other: "*"
  stage_map:
    devel: devel
    devel2: devel
    devel3: devel
    test: test
    live: live
  Secrets:
    devel:
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:fansifter-rds-k4b5VJ
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:fansifter-rds-dev-Vtyz6d
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:fb_credentials-xFOqu9
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:airflow-ui-pass-Z8rpW1
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:basic-admin-tools-access-5pJWrv
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:stripe-test-N6yCVs
    live:
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:fansifter-rds-live-W0X3AE
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:fb_credentials_live-SVOEqx
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:airflow-ui-pass-Z8rpW1
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:basic-admin-tools-access-5pJWrv
      - arn:aws:secretsmanager:eu-west-1:776891437216:secret:stripe-live-204bYd
    other:
      - "*"

  # If requirements.txt in ./layers are changed, the packages will be reinstalled using Docker and published as a layer
  # Otherwise, existing package layer will be used.
  layerCustomInstallationCommand: 'docker run --rm -v `pwd`:/var/task -w /var/task python:3.8-slim /bin/bash -c "apt-get update && apt-get install --no-install-recommends -y curl build-essential && pip install -r requirements.txt -t . && chmod -R a+w ./"'
  serverless-layers:
    - common: # reserved layer name, it will be automatically attached to all lambdas
        dependenciesPath: layers/common/requirements.txt
        packageManager: pip
        customInstallationCommand: ${{self:custom.layerCustomInstallationCommand}}
        compileDir: '.serverless/packages/common/'
        compatibleRuntimes:
          - 'python3.8'
    - heavy:
        functions:
          - EnrichmentRequests
          - SaveFanAttributeData
          - PostEnrichmentRequests
        dependenciesPath: layers/heavy/requirements.txt
        packageManager: pip
        customInstallationCommand: ${{self:custom.layerCustomInstallationCommand}}
        compileDir: '.serverless/packages/heavy/'
        compatibleRuntimes:
          - 'python3.8'

provider:
  name: aws
  runtime: python3.8
  stage: ${{opt:stage, 'devel'}}
  region: ${{opt:region, 'eu-west-1'}}
  # This is to allow mixing serverless variables with CloudFormation variables
  variableSyntax: "\\${{([ ~:a-zA-Z0-9._\\'\",\\-\\/\\(\\)]+?)}}"
  deploymentBucket:
    name: '${{self:custom.apiName}}-serverless-deployment-bucket'
    serverSideEncryption: AES256
  environment:
    PROFILE: ${{ self:custom.stage_map.${{self:provider.stage}} }}
    REGION: ${{self:provider.region}}

    DATA_PROCESSOR_URL: dataprocessor-${{ self:custom.stage_map.${{self:provider.stage}} }}.fansifter.cloud

    DB_SECRET_NAME: fansifter-rds-${{ self:custom.stage_map.${{self:provider.stage}} }}

    STRIPE_SECRET_NAME: ${{self:custom.stripeSecret.${{self:provider.stage}}, self:custom.stripeSecret.devel}}

    # Bucket name should not contain uppercase characters.
    USER_FILES_BUCKET_NAME: ${{self:service}}-${{ self:custom.stage_map.${{self:provider.stage}} }}-filestore
    SYSTEM_FILES_BUCKET_NAME: ${{self:service}}-${{ self:custom.stage_map.${{self:provider.stage}} }}-filestore-system

    USER_POOL_NAME: ${{self:custom.userPoolName}}

  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "s3:ListBucket"
      Resource:
        - arn:aws:s3:::${{self:provider.environment.USER_FILES_BUCKET_NAME}}
        - arn:aws:s3:::${{self:provider.environment.SYSTEM_FILES_BUCKET_NAME}}
        - arn:aws:s3:::fansifter-model-data
    - Effect: "Allow"
      Action:
        - "s3:GetObject"
        - "s3:PutObject"
        - "s3:GetObjectTagging"
      Resource:
        - arn:aws:s3:::${{self:provider.environment.USER_FILES_BUCKET_NAME}}/*
        - arn:aws:s3:::${{self:provider.environment.SYSTEM_FILES_BUCKET_NAME}}/*
        - arn:aws:s3:::fansifter-model-data/*
    - Effect: Allow
      Action:
        - secretsmanager:GetSecretValue
      Resource:
        ${{self:custom.Secrets.${{self:provider.stage}}, self:custom.Secrets.devel}}
    - Effect: 'Allow'
      Action:
        - appsync:GraphQL
      Resource:
        - ${{self:custom.appSyncAPI.${{self:provider.stage}}, self:custom.appSyncAPI.other}}
        - ${{self:custom.appSyncAPI.${{self:provider.stage}}, self:custom.appSyncAPI.other}}/types/*/fields/*


package:
  excludeDevDependencies: false
  exclude:
    - .idea/**
    - package-lock.json
    - .gitignore
    - coverage/**
    - static/**
    - index.test.js
    - .eslintrc
    - .eslintignore
    - python/**
    - venv/**
    - layers/**
    - requirements.txt
    - node_modules/**
    - functions/**
    - resources/**
    - package.json
    - README.md


layers:
  InternalPackages:
    name: ${{self:custom.apiName}}-python-internal
    compatibleRuntimes:
      - python3.8
    path: .
    package:
      include:
        - python/internal/*.py
        - python/management/*.py
        - python/product_packages/*.py
        - python/integration/**
        - python/airflow/**

  EnrichmentPackages:
    name: ${{self:custom.apiName}}-python-enrichment
    compatibleRuntimes:
      - python3.8
    path: .
    package:
      include:
        - python/analytics/**
        - python/enrichment/**
        - python/filtering/**
        - python/utils/**


functions:
  CognitoPostConfirmation:
    runtime: python3.8
    memorySize: 128
    description: "Cognito post-confirmation trigger handler."
    name: ${{self:custom.apiName}}-cognito-post-confirmation
    handler: python/cognito_post_confirmation.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/cognito_post_confirmation.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  CognitoPostAuthentication:
    runtime: python3.8
    memorySize: 128
    description: "Cognito post-confirmation trigger handler."
    name: ${{self:custom.apiName}}-cognito-post-authentication
    handler: python/cognito_post_authentication.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/cognito_post_authentication.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  S3UploadEvent:
    enabled: "['live','test','devel'].includes('${{self:provider.stage}}')"
    runtime: python3.8
    memorySize: 128
    timeout: 3
    description: "An Amazon S3 trigger that initiates post-upload processing."
    name: ${{self:custom.apiName}}-s3-upload-event-${{self:provider.environment.USER_FILES_BUCKET_NAME}}
    handler: python/s3_upload_event.lambda_handler
    events:
      - s3:
          bucket: ${{self:provider.environment.USER_FILES_BUCKET_NAME}}
          event: s3:ObjectCreated:Put
          existing: true
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-3193296b
        - subnet-9287cfda
        - subnet-75d6af13
    package:
      individually: true
      include:
        - python/s3_upload_event.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  OptOutHandler:
    enabled: "['live','test','devel'].includes('${{self:provider.stage}}')"
    runtime: python3.8
    memorySize: 128
    description: "handler for http://optout.fansifter.com/facebook"
    name: ${{self:custom.apiName}}-optout-handler
    handler: python/optout_handler.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-3193296b
        - subnet-9287cfda
        - subnet-75d6af13
    package:
      individually: true
      include:
        - python/optout_handler.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  PreSignupHandler:
    enabled: "['live','test','devel'].includes('${{self:provider.stage}}')"
    runtime: python3.8
    memorySize: 128
    description: "handler for http://optout.fansifter.com/pre-sign"
    name: ${{self:custom.apiName}}-pre-sign-handler
    handler: python/pre_signup_handler.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-3193296b
        - subnet-9287cfda
        - subnet-75d6af13
    package:
      individually: true
      include:
        - python/pre_signup_handler.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  StripeWebhookHandler:
    enabled: "['live','test','devel'].includes('${{self:provider.stage}}')"
    runtime: python3.8
    memorySize: 128
    description: "handler for http://optout.fansifter.com/stripe-webhook-{stage}"
    name: ${{self:custom.apiName}}-stripe-webhook-handler
    handler: python/stripe_webhook_handler.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/stripe_webhook_handler.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  InternalRequests:
    runtime: python3.8
    memorySize: 256
    timeout: 55
    description: "Internal requests servicing function."
    name: ${{self:custom.apiName}}-internal-requests
    handler: python/internal_requests.lambda_handler
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/internal_requests.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }

  EnrichmentRequests:
    runtime: python3.8
    memorySize: 10240
    timeout: 900
    description: "Running enrichments."
    name: ${{self:custom.apiName}}-enrichment-requests
    handler: python/enrichment_requests.lambda_handler
    fileSystemConfig:
      localMountPath: /mnt/efs
      arn: { "Fn::GetAtt": [ EFSAccessPoint, Arn ] }
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/enrichment_requests.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }
      - { Ref: EnrichmentPackagesLambdaLayer }
    dependsOn:
      - EFSMountTargetResource1
      - EFSMountTargetResource2
      - EFSMountTargetResource3
      - ElasticFileSystemForLambda

  PostEnrichmentRequests:
    runtime: python3.8
    memorySize: 256
    timeout: 240
    description: "Invoking post enrichment operations, like segmenting for algos."
    name: ${{self:custom.apiName}}-post-enrichment-requests
    handler: python/enrichment_requests.lambda_handler
    fileSystemConfig:
      localMountPath: /mnt/efs
      arn: { "Fn::GetAtt": [ EFSAccessPoint, Arn ] }
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/enrichment_requests.py
    layers:
      - { Ref: InternalPackagesLambdaLayer }
      - { Ref: EnrichmentPackagesLambdaLayer }
    dependsOn:
      - EFSMountTargetResource1
      - EFSMountTargetResource2
      - EFSMountTargetResource3
      - ElasticFileSystemForLambda


  SaveFanAttributeData:
    runtime: python3.8
    memorySize: 256
    timeout: 240
    description: "Saving enrichment data to fan_attribute table"
    name: ${{self:custom.apiName}}-save-fan-attribute-data
    handler: python/save_enrichment_data.lambda_handler
    fileSystemConfig:
      localMountPath: /mnt/efs
      arn: { "Fn::GetAtt": [ EFSAccessPoint, Arn ] }
    vpc:
      securityGroupIds:
        - sg-076956d5477d3ffe6
      subnetIds:
        - subnet-0677ce2c9e657a753
        - subnet-0f6924341618be842
        - subnet-09e418f466748e694
    package:
      individually: true
      include:
        - python/save_enrichment_data.py
    dependsOn:
      - EFSMountTargetResource1
      - EFSMountTargetResource2
      - EFSMountTargetResource3
      - ElasticFileSystemForLambda


resources:
  # Cognito
  - ${{file(resources/cognito.yml)}}
  # AppSync
  - ${{file(resources/appsync/schema.yml)}}
  - ${{file(resources/appsync/role.yml)}}
  - ${{file(resources/appsync/datasources.yml)}}
  - ${{file(resources/appsync/mutation_resolvers/mutation.yml)}}
  - ${{file(resources/appsync/query_resolvers/query.yml)}}
  - ${{file(resources/appsync/subscription_resolvers/subscription.yml)}}
  # S3
  - ${{file(resources/s3.yml)}}
  # EFS
  - ${{file(resources/efs.yml)}}
