AWSTemplateFormatVersion: 2010-09-09
Description: |
    Master Pipeline Lex Web UI CloudFormation template.
    It deploys:
        - S3 buckets to host the web application
        - CodeBuild project to build the configuration and deploy to S3
        - Optional Lex Bot (based on OrderFlowers example)
        - Optional Cognito Identity Pool for unauthenticated identities
        - Optional Lambda function to delete S3 buckets
        - CodeCommit Repository containg the source code in
          this project and a CodeBuild project, Lambda functions to initialize
          the repo
        - Optional deployment pipeline using CodePipeline and CodeBuild
        - CloudWatch Logs groups related to Lambda functions
        - Associated IAM roles

Parameters:
    BotName:
        Description: >
            Name of an existing Lex Bot to be used by the web ui.
            This is an optional parameter. If left empty, a Bot based
            on the OrderFlowers sample will be automatically created.
        Type: String
        Default: ''
        MaxLength: 50
        AllowedPattern: '(^$|^[a-zA-Z]+((_[a-zA-Z]+)*|([a-zA-Z]+_)*|_))'
        ConstraintDescription: >
            Must conform with the permitted Lex Bot name pattern.

    BotNamePrefix:
        Type: String
        Description: >
            Prefix to add to Lex resource names when using the sample bot.
            Ignored if you provide your own bot. Must conform to the
            permitted Lex Bot name syntax (alpha characters).
        Default: WebUi
        MinLength: 3
        MaxLength: 32
        AllowedPattern: '^[a-zA-Z\._]+$'
        ConstraintDescription: >
            Must conform with the permitted Lex Bot name pattern.

    ShouldDeleteBot:
        Type: String
        Default: true
        AllowedValues:
          - true
          - false
        Description: >
            If set to True, the Lex bot and associated resources will
            be deleted when the stack is deleted. Otherwise, the bot
            will be preserved. Only applies if the bot is created by
            this stack.

    CodeCommitRepoName:
        Type: String
        Description: >
            Name of CodeCommit repository to be created. Used as the
            source for the pipeline and to automate deployments of the
            web app. It is initialized with source artifacts from the
            bootstrap S3 bucket. Must be unique per region.
        Default: lex-web-ui
        MinLength: 1
        MaxLength: 100
        AllowedPattern: '^[\w\.-]+$'
        ConstraintDescription: Alphanumeric, dot and dash.

    CodePipelineName:
        Type: String
        Description: >
            Name of CodePipeline pipeline to be created. Used to manage
            the build and deployment of the web application. Must be
            unique per region.
            to true.
        Default: lex-web-ui
        MinLength: 1
        MaxLength: 100
        AllowedPattern: '[A-Za-z0-9.@\-_]+'
        ConstraintDescription: Alphanumeric, dot, dash, underscore and @.

    CodeBuildName:
        Type: String
        Description: >
            Name of the CodeBuild project to be created.  Used for
            building the web app with the pipeline. Must be unique
            per region.
        Default: lex-web-ui
        MinLength: 2
        MaxLength: 255
        AllowedPattern: '^[A-Za-z0-9][A-Za-z0-9\-_]{1,254}$'
        ConstraintDescription: >
            Should start with Alphanumeric. May contain alphanumeric, undescore
            and dash.

    WebAppParentOrigin:
        Type: String
        Description: >
            Browser origin (e.g. http://mysite.example.com:8080)
            of an existing site that is allowed to send/receive data
            and events from the web ui in an iframe setup. This is an
            optional parameter. If left empty, an S3 bucket will be
            created to host a sample parent site embedding the webapp
            as an iframe.
        Default: ''
        AllowedPattern: '(^$|^https?://[\w\.-]+(:\d+)?$)'
        ConstraintDescription: Empty or valid browser origin

    CognitoIdentityPoolId:
        Type: String
        Description: >
            Id of an existing Cognito Identity Pool. This is an optional
            parameter. If left empty, a Cognito Identity Pool will be
            automatically created. The pool ID is used by the web ui
            to get AWS credentials for making calls to Lex and Polly.
        Default: ''
        AllowedPattern: '(^$|^[\w-]+:[0-9a-f-]+$)'
        ConstraintDescription: Empty or a valid Cognito Identity Pool ID

    CognitoIdentityPoolName:
        Type: String
        Description: >
            Name of Cognito identity pool to be created to provide
            AWS credentials to the web ui. Only used if the
            CognitoIdentityPoolId parameter is left empty (default).
        Default: Lex Web UI
        MinLength: 1
        MaxLength: 128
        AllowedPattern: '^[\w ]+$'
        ConstraintDescription: Alphanumeric and spaces.

    CleanupBuckets:
        Type: String
        Default: true
        AllowedValues:
          - true
          - false
        Description: >
            If set to True, buckets created for the Pipeline and to store the
            web application will be deleted on CloudFormation stack delete.
            If set to False, S3 buckets will be retained.

    # Sub-templates and source artifacts are hosted in this bucket.
    # The content of this bucket is maintained outside of this template
    # by using the Makefile under the build directory of this project.
    # See the README.md file for instructions on how to use your own bucket.
    BootstrapBucket:
        Type: String
        Default: aws-bigdata-blog
        Description: >
            S3 bucket containing pre-staged nested templates and source artifacts
    BootstrapPrefix:
        Type: String
        Default: artifacts/aws-lex-web-ui/artifacts
        Description: >
            S3 prefix where the templates and source are stored under

Metadata:
    AWS::CloudFormation::Interface:
        ParameterGroups:
            - Label:
                default: Deployment Parameters
              Parameters:
                  - CodeBuildName
                  - CodePipelineName
                  - CodeCommitRepoName
                  - CleanupBuckets
                  - BootstrapBucket
                  - BootstrapPrefix
            - Label:
                default: Lex Bot Configuration Parameters
              Parameters:
                  - BotName
                  - BotNamePrefix
                  - ShouldDeleteBot
            - Label:
                default: Cognito Parameters
              Parameters:
                  - CognitoIdentityPoolId
                  - CognitoIdentityPoolName
            - Label:
                default: Web Application Parameters
              Parameters:
                  - WebAppParentOrigin

Conditions:
    NeedsBot: !Equals [!Ref BotName, '']
    NeedsCognito: !Equals [!Ref CognitoIdentityPoolId, '']
    NeedsParentOrigin: !Equals [!Ref WebAppParentOrigin, '']

Resources:
    Bot:
        Type: AWS::CloudFormation::Stack
        Condition: NeedsBot
        Properties:
            TimeoutInMinutes: 15
            TemplateURL: !Sub "https://s3.amazonaws.com/${BootstrapBucket}/${BootstrapPrefix}/templates/lexbot.yaml"
            Parameters:
                NamePrefix: !Ref BotNamePrefix
                ShouldDeleteBot: !Ref ShouldDeleteBot
                CustomResourceCodeBucket: !Ref BootstrapBucket
                CustomResourceCodeObject: !Sub "${BootstrapPrefix}/custom-resources.zip"

    CognitoIdentityPool:
        Type: AWS::CloudFormation::Stack
        Condition: NeedsCognito
        Properties:
            TemplateURL: !Sub "https://s3.amazonaws.com/${BootstrapBucket}/${BootstrapPrefix}/templates/cognito.yaml"
            Parameters:
                CognitoIdentityPoolName: !Ref CognitoIdentityPoolName
                LexBotName:
                    !If
                      - NeedsBot
                      - !GetAtt Bot.Outputs.BotName
                      - !Ref BotName

    ##########################################################################
    # deployment using a pipeline
    ##########################################################################
    CodeCommitRepo:
        Type: AWS::CloudFormation::Stack
        Properties:
            TimeoutInMinutes: 15
            TemplateURL: !Sub "https://s3.amazonaws.com/${BootstrapBucket}/${BootstrapPrefix}/templates/coderepo.yaml"
            Parameters:
                BotName:
                    !If
                      - NeedsBot
                      - !GetAtt Bot.Outputs.BotName
                      - !Ref BotName
                CodeBuildName: !Sub "${CodeCommitRepoName}-init"
                CodeCommitRepoName: !Ref CodeCommitRepoName
                CognitoIdentityPoolId:
                    !If
                      - NeedsCognito
                      - !GetAtt CognitoIdentityPool.Outputs.CognitoIdentityPoolId
                      - !Ref CognitoIdentityPoolId
                SourceBucket: !Ref BootstrapBucket
                SourceObject: !Sub "${BootstrapPrefix}/src.zip"
                CustomResourceCodeObject: !Sub "${BootstrapPrefix}/custom-resources.zip"

    Pipeline:
        Type: AWS::CloudFormation::Stack
        Properties:
            TemplateURL: !Sub "https://s3.amazonaws.com/${BootstrapBucket}/${BootstrapPrefix}/templates/pipeline.yaml"
            Parameters:
                BotName:
                    !If
                      - NeedsBot
                      - !GetAtt Bot.Outputs.BotName
                      - !Ref BotName
                CodePipelineName: !Ref CodePipelineName
                CodeCommitRepoName: !GetAtt CodeCommitRepo.Outputs.CodeCommitRepoName
                CodeBuildName: !Ref CodeBuildName
                CognitoIdentityPoolId:
                    !If
                      - NeedsCognito
                      - !GetAtt CognitoIdentityPool.Outputs.CognitoIdentityPoolId
                      - !Ref CognitoIdentityPoolId
                ParentOrigin: !Ref WebAppParentOrigin
                CustomResourceCodeBucket: !Ref BootstrapBucket
                CustomResourceCodeObject: !Sub "${BootstrapPrefix}/custom-resources.zip"
                CleanupBuckets: !Ref CleanupBuckets

Outputs:
    BotName:
        Condition: NeedsBot
        Description: >
            Name of the Lex bot created by the stack
        Value: !GetAtt Bot.Outputs.BotName

    CodeCommitRepoUrl:
        Description: CodeCommit repository clone URL
        Value: !GetAtt CodeCommitRepo.Outputs.CodeCommitRepoUrl

    PipelineUrl:
        Description: >
            Monitor the pipeline URL to see when the application has been fully
            built and deployed.
        Value: !Sub "https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline.Outputs.PipelineName}"

    WebAppUrl:
        Description: >
            URL of the stand-alone sample web application.
            This page will be available after the pipeline/deployment completes.
        Value: !GetAtt Pipeline.Outputs.WebAppUrl

    ParentPageUrl:
        Condition: NeedsParentOrigin
        Description: >
            URL of the iframe based sample web application
            This page will be available after the pipeline/deployment completes.
        Value: !GetAtt Pipeline.Outputs.ParentPageUrl

    LoaderScriptUrl:
        Description: >
            URL of the loader script
            This script will be available after the pipeline/deployment completes.
        Value: !GetAtt Pipeline.Outputs.LoaderScriptUrl

    SnippetUrl:
        Description: >
            URL of a page showing the snippet to load the chatbot UI as
            an iframe
        Value: !GetAtt Pipeline.Outputs.SnippetUrl

    CognitoIdentityPoolId:
        Condition: NeedsCognito
        Description: Cognito Identity Pool Id
        Value: !GetAtt CognitoIdentityPool.Outputs.CognitoIdentityPoolId
