AWSTemplateFormatVersion: "2010-09-09" Description: Amazon Transcribe Post Call Analytics - PCA Server - Boto3 Layer Zip Transform: AWS::Serverless-2016-10-31 Parameters: SupportFilesBucketName: Type: AWS::SSM::Parameter::Value Default: SupportFilesBucketName Boto3ZipName: Type: String Default: transcribeCallAnalyticsModels.zip Resources: boto3ZipFunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Resource: !Sub - 'arn:aws:s3:::${bucket}*' - bucket: !Ref SupportFilesBucketName Action: - 's3:PutObject' PolicyName: boto3ZipFunctionS3Policy boto3ZipFunction: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: python3.8 Role: !GetAtt 'boto3ZipFunctionRole.Arn' Timeout: 60 MemorySize: 512 Environment: Variables: SUPPORT_FILES_BUCKET: !Ref SupportFilesBucketName BOTO3_ZIP_NAME: !Ref Boto3ZipName Code: ZipFile: | # Package up the Transcribe model version that we need from boto3 (missing from Lambda @ 10/1/2021) # This can all be removed on Lambda supports Call Analytics APIs withing its built-in boto3 version import os import boto3 import urllib.request import tarfile from zipfile import ZipFile import cfnresponse import sys import shutil import subprocess bucket = os.environ['SUPPORT_FILES_BUCKET'] boto_zip_file_name = os.environ['BOTO3_ZIP_NAME'] def handler(event, context): responseData={} status = cfnresponse.SUCCESS if event['RequestType'] != 'Delete': try: # Shift to the tmp folder, as we're writing files root_path = '/tmp' os.chdir(root_path) # Create a folder to hold the boto3 download pip_folder = "LocalPipFolder" os.mkdir(pip_folder) # Create a folder structure to mimic the boto3 model setup for Transcribe zip_folder = "models" zip_subfolder_1 = "transcribe" zip_subfolder_2 = "2017-10-26" reqs_file = "requirements.txt" zip_folders = [zip_folder,zip_subfolder_1,zip_subfolder_2] for folder in zip_folders: root_path = os.path.join(root_path,folder) os.mkdir(root_path) # Write out the requirements.txt file, which is the boto3 version we need with open(reqs_file, 'w') as f: f.write("boto3==1.24.2") f.close() # Install this version of boto3 locally and copy out Transcribe model subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", reqs_file, "-t", pip_folder]) shutil.copy(f"{pip_folder}/botocore/data/{zip_subfolder_1}/{zip_subfolder_2}/service-2.json", "/".join(zip_folders)) # Zip up the models folder, maintaining the folder structure with ZipFile(boto_zip_file_name, 'w') as zipObj: for folderName, subfolders, filenames in os.walk(zip_folder): for filename in filenames: #create complete filepath of file in directory filePath = os.path.join(folderName, filename) # Add file to zip print(f"zipping {filePath}") zipObj.write(filePath) # Upload zipfile to S3 print(f"uploading {boto_zip_file_name} to s3 bucket {bucket}") s3_client = boto3.client('s3') response = s3_client.upload_file(boto_zip_file_name, bucket, boto_zip_file_name) except Exception as e: print(e) responseData["Error"] = f"Exception thrown: {e}" status = cfnresponse.FAILED cfnresponse.send(event, context, status, responseData) boto3Zip: Type: Custom::boto3Zip Properties: ServiceToken: !GetAtt boto3ZipFunction.Arn Boto3Layer: Type: "AWS::Lambda::LayerVersion" DependsOn: boto3Zip Properties: Content: S3Bucket: !Ref SupportFilesBucketName S3Key: !Ref Boto3ZipName Outputs: Boto3Layer: Description: Lambda layer for Boto3 that other Lambdas may need Value: !Ref Boto3Layer