aws-lex-web-ui icon indicating copy to clipboard operation
aws-lex-web-ui copied to clipboard

CloudFormation Stack stuck at CREATE_IN_PROGRESS

Open harshadabhanose opened this issue 5 years ago • 8 comments

I am trying to deploy the project using my own bootstrap S3 bucket. I have followed below process for the same:

  1. Create your own S3 bucket
  2. Modify the variables in the local build environment file: config/env.mk.
    • BOOTSTRAP_BUCKET_PATH
  3. Upload the files to my S3 bucket using make upload from the build directory under the root of the repo.
  4. Deploy the stack by using the master.yml template. Change the the BootstrapBucket and BootstrapPrefix parameters to point to my own bucket and path

However, when I create a stack using CloudFormation, only the Cognito identity pool is deployed successfully and the process gets stuck at event CodeBuildStarter and eventually S3Cleanup fails with reason

Custom Resource failed to stabilize in expected time

The CloudWatch logs show an error

Unable to import module 'codebuild-start': No module named codebuild-start

Can you please help in this issue?

harshadabhanose avatar Aug 18 '18 13:08 harshadabhanose

I assume you have your own bot created in lex ready to go as creating the default OrderFlows bot would normally be the first nested stack run by the master.yml template. It sounds like the make upload is not completing all the work required. I've been running the available shell scripts in the build directory manually and have been having success using these to create my bootstrap bucket. You might try the following in a shell assuming your are on a mac or linux system

cd build export BUCKET=<YOUR_S3_BUCKET_NAME> ./release.sh ./upload-bootstrap.sh

The release.sh will perform a full build and then upload-bootstrap.sh will upload the artifacts to YOUR_S3_BUCKET_NAME/artifacts location.

Then you can try running cloudformation again using the master.yml with a new stack in either the us-east-1 or us-west-2 regions. You would adjust the BootstrapBucket to be your bucket name and the BootstrapPrefix to be artifacts.

If this works then perhaps compare the artifacts from make upload against the artifacts from the upload-bootstrap.sh. Something I would suspect will be different. Let me know if this helps. If not let me know what your local build environment looks like (Windows/Mac/Linux and - version) and I can try replicating your setup.

bobpskier avatar Aug 20 '18 01:08 bobpskier

Thank you @bobpskier , tried your solution but still getting the same error. The event for Custom::CodeBuildStarter is stuck as shown in below screenshot. image

The CloudWatch logs still show the same error:

Unable to import module 'codebuild-start': No module named codebuild-start

My codebuild-deploy.yaml template is as follows:

AWSTemplateFormatVersion: 2010-09-09
Description: >
    This template creates a CodeBuild project used to configure and deploy
    the chatbot UI

Parameters:
    CodeBuildName:
        Type: String
        Description: CodeBuild project used to configure and deploy the Lex Web UI
        Default: lex-web-ui-conf-deploy
        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.

    SourceBucket:
        Description: S3 bucket where the source is located
        Type: String
        Default: bizamica

    SourceObject:
        Description: S3 object zip file containing the project source
        Type: String
        Default: artifacts/aws-lex-web-ui/artifacts/src.zip

    CustomResourceCodeObject:
        Type: String
        Description: >
            S3 object zip file containing Lambda custom resource functions
        Default: artifacts/aws-lex-web-ui/artifacts/custom-resources.zip

    CleanupBuckets:
        Type: String
        Default: true
        AllowedValues:
          - true
          - false
        Description: >
            If set to True, buckets and their associated data will be deleted on
            CloudFormation stack delete. If set to False, S3 buckets will be retained.

    CognitoIdentityPoolId:
        Type: String
        Description: >
            Cognito Identity Pool Id to used in the web app configuration.
        MinLength: 1
        MaxLength: 55
        AllowedPattern: '^[\w-]+:[0-9a-f-]+$'
        ConstraintDescription: >
            Alphanumeric followed by a colum and ending with a hex uuid type.

    BotName:
        Description: >
            Name of Lex bot to be used in the web app configuration.
        Type: String
        MinLength: 2
        MaxLength: 50
        AllowedPattern: '^[a-zA-Z]+((_[a-zA-Z]+)*|([a-zA-Z]+_)*|_)'
        ConstraintDescription: >
            Must conform with the permitted Lex Bot name pattern.

    ParentOrigin:
        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.
        AllowedPattern: '(^$|^https?://[\w\.-]+(:\d+)?$)'
        ConstraintDescription: Empty or valid browser origin

    WebAppConfBotInitialText:
        Type: String
        Default: >
            You can ask me for help ordering flowers. Just type "Buy
            flowers" or click on the mic and say it.
        Description: First bot message displayed in the chatbot UI

    WebAppConfBotInitialSpeech:
        Type: String
        Default: Say 'Buy Flowers' to get started.
        Description: >
            Message spoken by bot when the microphone is first pressed
            in a conversation

    WebAppConfToolbarTitle:
        Type: String
        Default: Order Flowers
        Description: Title displayed in the chatbot UI toobar

Conditions:
    NeedsParentOrigin: !Equals [!Ref ParentOrigin, '']
    ShouldCleanupBuckets: !Equals [!Ref CleanupBuckets, true]

Resources:
    # Bucket where the web app is deployed
    WebAppBucket:
        Type: AWS::S3::Bucket
        DeletionPolicy: Retain
        Properties:
            WebsiteConfiguration:
                IndexDocument: index.html
            VersioningConfiguration:
                Status: Enabled
            CorsConfiguration:
                !If
                  - NeedsParentOrigin
                  - !Ref AWS::NoValue
                  - CorsRules:
                    - AllowedMethods:
                        - GET
                      AllowedOrigins:
                        - !Ref ParentOrigin

    CodeBuild:
        Type: AWS::CodeBuild::Project
        Properties:
            Name: !Ref CodeBuildName
            Description: Used to configure and deploy the Lex Web UI
            Artifacts:
                Type: NO_ARTIFACTS
            Environment:
                Type: LINUX_CONTAINER
                Image: aws/codebuild/nodejs:8.11.0
                ComputeType: BUILD_GENERAL1_SMALL
                EnvironmentVariables:
                    - Name: BUILD_TYPE
                      Value: dist
                    - Name: POOL_ID
                      Value: !Ref CognitoIdentityPoolId
                    - Name: WEBAPP_BUCKET
                      Value: !Ref WebAppBucket
                    - Name: AWS_DEFAULT_REGION
                      Value: !Sub "${AWS::Region}"
                    - Name: BOT_NAME
                      Value: !Ref BotName
                    - Name: BOT_INITIAL_TEXT
                      Value: !Ref WebAppConfBotInitialText
                    - Name: BOT_INITIAL_SPEECH
                      Value: !Ref WebAppConfBotInitialSpeech
                    - Name: UI_TOOLBAR_TITLE
                      Value: !Ref WebAppConfToolbarTitle
                    - Name: PARENT_ORIGIN
                      Value: !If
                        - NeedsParentOrigin
                        - !Sub "https://${WebAppBucket.DomainName}"
                        - !Ref ParentOrigin
                    - Name: IFRAME_ORIGIN
                      Value: !Sub "https://${WebAppBucket.DomainName}"
            ServiceRole: !GetAtt CodeBuildRole.Arn
            TimeoutInMinutes: 10
            Source:
                Type: S3
                Location: !Sub "${SourceBucket}/${SourceObject}"
                BuildSpec: !Sub |
                    version: 0.1
                    phases:
                        pre_build:
                            commands:
                                - aws configure set region "$AWS_DEFAULT_REGION"
                                - make config
                        post_build:
                            commands:
                                - make sync-website

    # custom resource to start code build project
    CodeBuildStarter:
        Type: Custom::CodeBuildStarter
        Properties:
            ServiceToken: !GetAtt CodeBuildStarterLambda.Arn
            ProjectName: !Ref CodeBuild

    # Lambda function for custom resource
    CodeBuildStarterLambda:
        Type: AWS::Lambda::Function
        Properties:
            Code:
                S3Bucket: !Ref SourceBucket
                S3Key: !Ref CustomResourceCodeObject
            Handler: codebuild-start.handler
            Role: !GetAtt CodeBuildStarterLambdaRole.Arn
            Runtime: python2.7
            Timeout: 120

    CodeBuildRole:
        Type: AWS::IAM::Role
        Properties:
            Path: /
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Principal:
                          Service:
                              - codebuild.amazonaws.com
                      Effect: Allow
                      Action:
                          - sts:AssumeRole
            Policies:
                - PolicyName: S3GetObject
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - s3:GetObject*
                            Resource:
                                - !Sub "arn:aws:s3:::${SourceBucket}/${SourceObject}"
                - PolicyName: S3ReadWrite
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - s3:Get*
                                - s3:Head*
                                - s3:List*
                                - s3:CreateMultipartUpload
                                - s3:CompleteMultipartUpload
                                - s3:AbortMultipartUpload
                                - s3:CopyObject
                                - s3:PutObject*
                                - s3:DeleteObject*
                                - s3:Upload*
                            Resource:
                                - !Sub "arn:aws:s3:::${WebAppBucket}"
                                - !Sub "arn:aws:s3:::${WebAppBucket}/*"
                - PolicyName: CloudWatchLogsCodeBuild
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - logs:CreateLogGroup
                                - logs:CreateLogStream
                                - logs:PutLogEvents
                            Resource:
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${CodeBuildName}"
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${CodeBuildName}:*"

    CodeBuildStarterLambdaRole:
        Type: AWS::IAM::Role
        Properties:
            Path: /
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Principal:
                          Service:
                              - lambda.amazonaws.com
                      Effect: Allow
                      Action:
                          - sts:AssumeRole
            Policies:
                - PolicyName: LogsForLambda
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - logs:CreateLogGroup
                                - logs:CreateLogStream
                                - logs:PutLogEvents
                            Resource:
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*:*"
                - PolicyName: CodeBuildStart
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - codebuild:StartBuild
                            Resource: !GetAtt CodeBuild.Arn

    # custom resource to cleanup S3 buckets
    S3Cleanup:
        Type: Custom::S3Cleanup
        Condition: ShouldCleanupBuckets
        Properties:
            ServiceToken: !GetAtt S3CleanupLambda.Arn
            Buckets:
                - !Ref WebAppBucket

    # Lambda function for custom resource
    S3CleanupLambda:
        Type: AWS::Lambda::Function
        Condition: ShouldCleanupBuckets
        Properties:
            Code:
                S3Bucket: !Ref SourceBucket
                S3Key: !Ref CustomResourceCodeObject
            Handler: s3-cleanup.handler
            Role: !GetAtt S3CleanupLambdaRole.Arn
            Runtime: python2.7
            Timeout: 120

    S3CleanupLambdaRole:
        Type: AWS::IAM::Role
        Condition: ShouldCleanupBuckets
        Properties:
            Path: /
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Principal:
                          Service:
                              - lambda.amazonaws.com
                      Effect: Allow
                      Action:
                          - sts:AssumeRole
            Policies:
                - PolicyName: LogsForLambda
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - logs:CreateLogGroup
                                - logs:CreateLogStream
                                - logs:PutLogEvents
                            Resource:
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
                                - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*:*"
                - PolicyName: S3All
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                                - s3:*
                            Resource:
                                - !Sub "arn:aws:s3:::${WebAppBucket}"
                                - !Sub "arn:aws:s3:::${WebAppBucket}/*"

Outputs:
    CodeBuildProject:
        Description: CodeBuild project name
        Value: !Ref CodeBuild

    WebAppUrl:
        Value: !Sub "https://${WebAppBucket.DomainName}/index.html"
        Description: URL of the web application

    ParentPageUrl:
        Value: !Sub "https://${WebAppBucket.DomainName}/parent.html"
        Description: URL of the sample parent page

    LoaderScriptUrl:
        Value: !Sub "https://${WebAppBucket.DomainName}/lex-web-ui-loader.min.js"
        Description: URL of the loader script

    SnippetUrl:
        Value: !Sub "https://${WebAppBucket.DomainName}/iframe-snippet.html"
        Description: URL of a page showing the snippet to load the chatbot UI as an iframe

I am using Cygwin on Windows10 to build this project.

The artifacts uploaded in both cases are identical except the BOOTSTRAP_BUCKET_PATH. And I can see the custom lambda function codebuild-start.py in the zip file custom-resporces.zip. My S3 bucket has full public access (access provided to check if its a permission issue). Still the CodeBuild is not able to access it. Does this have to do with any access/permissions/roles/policy related issue?

harshadabhanose avatar Aug 20 '18 06:08 harshadabhanose

What permissions is your AWS user setup with? It is possible permissions are related however I've not seen any evidence of this yet but lets check out the Lambda function the cloud formation template is trying to execute. If I'm reading your screenshot correctly, the cloud formation template has just finished creating the CodeBuildStarterLambda function and is now trying to execute this function. Using the Lambda console please verify that the new function does exist and looks correct. You should see something like:

image

Next checkout the cloudwatch logs for this function:

/aws/lambda/[YOURSTACKNAME]-CodeBuildDeplo-CodeBuildStarterLambda-NNNNNNNNNNNN

From appearances this function is encountering an error and is not terminating gracefully. See if this log indicates any failure. You might see a permission or some other exception logged here.

bobpskier avatar Aug 20 '18 12:08 bobpskier

@bobpskier I am using an admin account.

Verified in the lambda console, I am able to see the custom function. image

The CloudWatch logs for this function show the same following error with 2 more retries. Nothing related to permissions / any other exception logged there:

Unable to import module 'codebuild-start': No module named codebuild-start

harshadabhanose avatar Aug 20 '18 16:08 harshadabhanose

I'm wondering if Cygwin is packaging up the zip for deployment in some weird way. The error seems to indicate that Lambda can't find the file codebuild-start.py. Your screen shot seems to indicate that codebuild-start.py does exist. The codebuild-deploy.yaml looks good as well. However the error seems to indicate some sort of issue in this area. Have you tried testing/editing/renaming the function directly in Lambda? Maybe make a duplicate of the function, delete the original, and rename back to code build-start.py via the inline code editing in Lambda? Also I've had success using the newer Windows 10 Linux subsystem https://docs.microsoft.com/en-us/windows/wsl/install-win10 via the ubuntu distribution to package and deploy Lambda functions from Windows 10. I've not used Cygwin in quite some time.

bobpskier avatar Aug 21 '18 13:08 bobpskier

I am having the same problem once I try to use custom created s3 bucket, cloudformation will fail at cresating s3 bucket. I wonder if I setup my BOOTSTRAP_BUCKET_PATH in wrong way. What exactly is BOOTSTRAP_BUCKET_PATH ? I couldn't find anywhere on internet.

Samjin avatar Aug 27 '18 16:08 Samjin

BOOTSTRAP_BUCKET_PATH defined in config/env.mk is a string containing the values of BootstrapBucket and BootstrapPrefix joined by a "/" both of which are also parameters to the CloudFormation template. It would look something like "yourstackname-lexuibuildartifactbucket-146vrxfh5zag5/artifacts/aws-lex-web-ui/artifacts". The values identify where you want to output artifacts as a result of a build of the lex-web-ui. The CloudFormation template when run asks for the location of the BootstrapBucket and the BootstrapPrefix but does not update these. After the CloudFormation template is run, a new S3 bucket will contain the deployed lex-web-ui configured based on the supplied parameters. The "Bootstrap" parameters identify a staging area where the components can be deployed from.

bobpskier avatar Aug 29 '18 12:08 bobpskier

I think one possible cause may be the case when you delete a bucket and then try and reuse the same name. The bucket name can be blocked for a while while AWS updates. I noticed this when trying to manually create the bucket in the console. When I tried using a bucket with a different name it worked and the CDK bootstrapping no longer hangs on create_in_progress. https://aws.amazon.com/premiumsupport/knowledge-center/s3-conflicting-conditional-operation/#:~:text=You%20can%20get%20the%20error,of%20deleting%20the%20original%20bucket.&text=However%2C%20when%20the%20bucket%20is,can%20use%20the%20bucket%20name.

HeskethGD avatar Apr 19 '21 11:04 HeskethGD