Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to deploy a Lex bot using CDK?

I want to deploy a Lex bot to my AWS account using CDK.

Looking at the API reference documentation I can't find a construct for Lex. Also, I found this issue on the CDK GitHub repository which confirms there is no CDK construct for Lex.

Is there any workaround to deploy the Lex bot or another tool for doing this ?

like image 767
eldercookie Avatar asked Nov 06 '22 07:11

eldercookie


1 Answers

Edit: CloudFormation support for AWS Lex is now available, see Wesley Cheek's answer. Below is my original answer which solved the lack of CloudFormation support using custom resources.

There is! While perhaps a bit cumbersome, it's totally possible using custom resources.

Custom resources work by defining a lambda that handles creation and deletion events for the custom resource. Since it's possible to create and delete AWS Lex bots using the AWS API, we can make the lambda do this when the resource gets created or destroyed.

Here's a quick example I wrote in TS/JS:

CDK Code (TypeScript):

import * as path from 'path';
import * as cdk from '@aws-cdk/core';
import * as iam from '@aws-cdk/aws-iam';
import * as logs from '@aws-cdk/aws-logs';
import * as lambda from '@aws-cdk/aws-lambda';
import * as cr from '@aws-cdk/custom-resources';

export class CustomResourceExample extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Lambda that will handle the different cloudformation resource events
    const lexBotResourceHandler = new lambda.Function(this, 'LexBotResourceHandler', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'lambdas')),
      handler: 'lexBotResourceHandler.handler',
      runtime: lambda.Runtime.NODEJS_14_X,
    });
    lexBotResourceHandler.addToRolePolicy(new iam.PolicyStatement({
      resources: ['*'],
      actions: ['lex:PutBot', 'lex:DeleteBot']
    }))

    // Custom resource provider, specifies how the custom resources should be created
    const lexBotResourceProvider = new cr.Provider(this, 'LexBotResourceProvider', {
      onEventHandler: lexBotResourceHandler,
      logRetention: logs.RetentionDays.ONE_DAY // Default is to keep forever
    });

    // The custom resource, creating one of these will invoke the handler and create the bot
    new cdk.CustomResource(this, 'ExampleLexBot', {
      serviceToken: lexBotResourceProvider.serviceToken,

      // These options will be passed down to the lambda
      properties: {
        locale: 'en-US',
        childDirected: false
      }
    })
  }
}

Lambda Code (JavaScript):

const AWS = require('aws-sdk');
const Lex = new AWS.LexModelBuildingService();

const onCreate = async (event) => {
  await Lex.putBot({
    name: event.LogicalResourceId,
    locale: event.ResourceProperties.locale,
    childDirected: Boolean(event.ResourceProperties.childDirected)
  }).promise();
};

const onUpdate = async (event) => {
  // TODO: Not implemented
};

const onDelete = async (event) => {
  await Lex.deleteBot({
    name: event.LogicalResourceId
  }).promise();
};

exports.handler = async (event) => {
  switch (event.RequestType) {
    case 'Create':
      await onCreate(event);
      break;

    case 'Update':
      await onUpdate(event);
      break;

    case 'Delete':
      await onDelete(event);
      break;
  }
};

I admit it's a very bare-bones example but hopefully it's enough to get you or anyone reading started and see how it could be built upon by adding more options and more custom resources (for example for intentions).

like image 98
White Autumn Avatar answered Jan 01 '23 15:01

White Autumn