Creación de una aplicación de procesamiento de archivos sin servidor - AWS Lambda

Creación de una aplicación de procesamiento de archivos sin servidor

Uno de los casos de uso más comunes de Lambda es llevar a cabo tareas de procesamiento de archivos. Por ejemplo, puede utilizar una función de Lambda para crear archivos PDF de forma automática a partir de archivos HTML o imágenes, o para crear miniaturas cuando un usuario carga una imagen.

En este ejemplo, crea una aplicación que cifra los archivos PDF de forma automática cuando se cargan en un bucket de Amazon Simple Storage Service (Amazon S3). Para implementar esta aplicación, necesita crear los siguientes recursos:

  • Un bucket de S3 para que los usuarios puedan cargar los archivos PDF

  • Una función de Lambda en Python que lea el archivo cargado y cree una versión cifrada y protegida por contraseña

  • Un segundo bucket de S3 en el que Lambda pueda guardar el archivo cifrado

También debe crear una política de AWS Identity and Access Management (IAM) para conceder permiso a la función de Lambda para llevar a cabo operaciones de lectura y escritura en los buckets de S3.

Diagrama que muestra el flujo de datos entre un bucket de S3, una función de Lambda y otro bucket de S3
sugerencia

Si es la primera vez que utiliza Lambda, recomendamos que comience por el tutorial de Creación de su primera función de Lambda antes de crear esta aplicación de ejemplo.

Para implementar la aplicación de forma manual, cree y configure los recursos mediante la AWS Management Console o con la AWS Command Line Interface (AWS CLI). También puede implementar la aplicación mediante AWS Serverless Application Model (AWS SAM). AWS SAM es una herramienta de Infraestructura como código (IaC). Con la IaC no se crean recursos de forma manual, sino que se definen en código y, a continuación, se implementan automáticamente.

Si desea obtener más información sobre el uso de Lambda con la IaC antes de implementar esta aplicación de ejemplo, consulte Uso de Lambda con la infraestructura como código (IaC).

Crear los archivos de código fuente de la función de Lambda

Cree los siguientes archivos en el directorio del proyecto:

  • lambda_function.py: es el código de la función Python para la función de Lambda que lleva a cabo el cifrado de archivos

  • requirements.txt: es un archivo de manifiesto que define las dependencias que requiere el código de la función de Python

Expanda las siguientes secciones para ver el código y obtener más información sobre la función de cada archivo. Para crear los archivos en la máquina local, copie y pegue el siguiente código o descargue los archivos del repositorio de GitHub aws-lambda-developer-guide.

Copie y pegue el siguiente código en un archivo denominado lambda_function.py.

from pypdf import PdfReader, PdfWriter import uuid import os from urllib.parse import unquote_plus import boto3 # Create the S3 client to download and upload objects from S3 s3_client = boto3.client('s3') def lambda_handler(event, context): # Iterate over the S3 event object and get the key for all uploaded files for record in event['Records']: bucket = record['s3']['bucket']['name'] key = unquote_plus(record['s3']['object']['key']) # Decode the S3 object key to remove any URL-encoded characters download_path = f'/tmp/{uuid.uuid4()}.pdf' # Create a path in the Lambda tmp directory to save the file to upload_path = f'/tmp/converted-{uuid.uuid4()}.pdf' # Create another path to save the encrypted file to # If the file is a PDF, encrypt it and upload it to the destination S3 bucket if key.lower().endswith('.pdf'): s3_client.download_file(bucket, key, download_path) encrypt_pdf(download_path, upload_path) encrypted_key = add_encrypted_suffix(key) s3_client.upload_file(upload_path, f'{bucket}-encrypted', encrypted_key) # Define the function to encrypt the PDF file with a password def encrypt_pdf(file_path, encrypted_file_path): reader = PdfReader(file_path) writer = PdfWriter() for page in reader.pages: writer.add_page(page) # Add a password to the new PDF writer.encrypt("my-secret-password") # Save the new PDF to a file with open(encrypted_file_path, "wb") as file: writer.write(file) # Define a function to add a suffix to the original filename after encryption def add_encrypted_suffix(original_key): filename, extension = original_key.rsplit('.', 1) return f'{filename}_encrypted.{extension}'
nota

En este código de ejemplo, la contraseña del archivo cifrado (my-secret-password) está codificada en el código de la función. En aplicaciones de producción, no incluya información confidencial como contraseñas en el código de la función. Utilice AWS Secrets Manager para almacenar los parámetros confidenciales de forma segura.

El código de la función de Python contiene tres funciones: la función de controlador que Lambda ejecuta cuando se invoca la función y dos funciones independientes denominadas add_encrypted_suffix y encrypt_pdf a las que el controlador llama para que lleve a cabo el cifrado del PDF.

Cuando Amazon S3 invoca la función, Lambda pasa un argumento de evento con formato JSON a la función que contiene detalles sobre el evento que provocó la invocación. En este caso, la información incluye el nombre del bucket de S3 y las claves de objeto de los archivos cargados. Para obtener más información sobre el formato del objeto de evento de Amazon S3, consulte Procese las notificaciones de eventos de Amazon S3 con Lambda..

A continuación, la función utiliza AWS SDK for Python (Boto3) para descargar los archivos PDF especificados en el objeto de evento a su directorio de almacenamiento temporal local, antes de cifrarlos mediante la biblioteca pypdf.

Por último, la función utiliza el SDK de Boto3 para almacenar el archivo cifrado en el bucket de destino de S3.

Copie y pegue el siguiente código en un archivo denominado requirements.txt.

boto3 pypdf

En este ejemplo, el código de la función solo tiene dos dependencias que no forman parte de la biblioteca estándar de Python: el SDK para Python (Boto3) y el paquete pypdf que la función utiliza para cifrar el PDF.

nota

Como parte del tiempo de ejecución de Lambda, se incluye una versión del SDK para Python (Boto3), de modo que el código se ejecute sin agregar Boto3 al paquete de implementación de la función. Sin embargo, para mantener el control total de las dependencias de la función y evitar posibles problemas de alineación de versiones, la práctica recomendada para Python es incluir todas las dependencias de la función en el paquete de implementación de la función. Consulte Dependencias de tiempo de ejecución en Python para obtener más información.

Implementar la aplicación

Puede crear e implementar los recursos para esta aplicación de ejemplo de forma manual o mediante AWS SAM. En un entorno de producción, recomendamos que utilice una herramienta de IaC como AWS SAM para implementar aplicaciones sin servidor de forma rápida y repetible sin utilizar procesos manuales.

Para implementar la aplicación manualmente:

  • Cree buckets de Amazon S3 de origen y de destino

  • Cree una función de Lambda que cifre un archivo PDF y guarde la versión cifrada de este en un bucket de S3

  • Configure un desencadenador de Lambda que invoque la función cuando se carguen objetos en el bucket de origen

Antes de comenzar, asegúrese de que Python esté instalado en el equipo de compilación.

Cree dos buckets de S3

Primero, cree dos buckets de S3. El primer bucket es el bucket de origen al que subirá los archivos PDF. Lambda utiliza el segundo bucket para guardar el archivo cifrado cuando se invoca la función.

Console
Para crear buckets de S3 (consola)
  1. En la consola de Amazon S3, abra la página Buckets.

  2. Seleccione la Región de AWS más cercana a su ubicación geográfica. Puede cambiar la región por medio de la lista desplegable de la parte superior de la pantalla.

    Imagen que muestra el menú desplegable de regiones en la consola de S3
  3. Elija Crear bucket.

  4. En Configuración general, haga lo siguiente:

    1. Para el Tipo de bucket, seleccione Uso general.

    2. Para el Nombre del bucket, ingrese un nombre único a nivel mundial que cumpla las reglas de nomenclatura de bucket de Amazon S3. Los nombres de bucket pueden contener únicamente letras minúsculas, números, puntos (.) y guiones (-).

  5. Deje el resto de las opciones con sus valores predeterminados y seleccione Crear bucket.

  6. Repita los pasos 1 a 4 para crear el bucket de destino. En Nombre del bucket, introduzca amzn-s3-demo-bucket-encrypted, donde amzn-s3-demo-bucket es el nombre del bucket de origen que acaba de crear.

AWS CLI

Antes de comenzar, asegúrese de que la AWS CLI esté instalada en el equipo de compilación.

Para crear buckets de Amazon S3 (AWS CLI)
  1. Ejecute el siguiente comando de la CLI para crear el bucket de origen. El nombre que elija para el bucket debe ser globalmente único y seguir las reglas de nomenclatura de buckets de Amazon S3. Los nombres pueden contener únicamente letras minúsculas, números, puntos (.) y guiones (-). Para region y LocationConstraint, elija la Región de AWS más cercana a su ubicación geográfica.

    aws s3api create-bucket --bucket amzn-s3-demo-bucket --region us-east-2 \ --create-bucket-configuration LocationConstraint=us-east-2

    Más adelante en el tutorial, debe crear la función de Lambda en la misma Región de AWS que la del bucket de origen, por lo que debe anotar la región que eligió.

  2. Ejecute el siguiente comando para crear el bucket de destino. Para el nombre del bucket, debe utilizar amzn-s3-demo-bucket-encrypted, donde amzn-s3-demo-bucket es el nombre del bucket de origen que creó en el paso 1. Para region y LocationConstraint, elija la misma Región de AWS que usó para crear el bucket de origen.

    aws s3api create-bucket --bucket amzn-s3-demo-bucket-encrypted --region us-east-2 \ --create-bucket-configuration LocationConstraint=us-east-2

Creación de un rol de ejecución

Un rol de ejecución es un rol de IAM que concede a la función de Lambda permiso para acceder a servicios y recursos de Servicios de AWS. Para conceder acceso de lectura y escritura a Amazon S3 a la función, debe adjuntar la política administrada de AWS AmazonS3FullAccess.

Console
Para crear un rol de ejecución y adjuntar la política administrada AmazonS3FullAccess (consola)
  1. Abra la página Roles en la consola de IAM.

  2. Elija Crear rol.

  3. En Tipo de entidad de confianza, seleccione Servicio de AWS y, en Caso de uso, seleccione Lambda.

  4. Elija Siguiente.

  5. Agregue la política administrada AmazonS3FullAccess de la siguiente manera:

    1. En Políticas de permisos, ingrese AmazonS3FullAccess en la barra de búsqueda.

    2. Seleccione la casilla situada junto a la política administrada.

    3. Elija Siguiente.

  6. En Detalles del rol, para Nombre de rol, escriba LambdaS3Role.

  7. Seleccione Creación de rol.

AWS CLI
Crear un rol de ejecución y adjuntar la política administrada AmazonS3FullAccess (AWS CLI)
  1. Guarde el siguiente JSON en un archivo llamado trust-policy.json. Esta política de confianza permite a Lambda utilizar los permisos del rol al dar permiso al servicio principal lambda.amazonaws.com para llamar a la acción de AWS Security Token Service (AWS STS) AssumeRole.

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
  2. Desde el directorio en el que guardó el documento de política de confianza JSON, ejecute el siguiente comando de la CLI para crear el rol de ejecución.

    aws iam create-role --role-name LambdaS3Role --assume-role-policy-document file://trust-policy.json
  3. Para adjuntar la política administrada AmazonS3FullAccess, ejecute el siguiente comando de la CLI:

    aws iam attach-role-policy --role-name LambdaS3Role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

Crear el paquete de despliegue de la función

Para crear una función, debe crear un paquete de despliegue que contenga el código y las dependencias de la función. Para esta aplicación, el código de la función utiliza una biblioteca independiente para el cifrado de PDF.

Creación del paquete de implementación
  1. Navegue hasta el directorio del proyecto que contiene los archivos lambda_function.py y requirements.txt que creó o descargó de GitHub anteriormente y cree un nuevo directorio denominado package.

  2. Instale las dependencias especificadas en el archivo requirements.txt del directorio package ejecutando el siguiente comando:

    pip install -r requirements.txt --target ./package/
  3. Cree un archivo .zip que contenga el código de la aplicación y todas sus dependencias. En Linux o macOS, ejecute los siguientes comandos desde la interfaz de la línea de comandos.

    cd package zip -r ../lambda_function.zip . cd .. zip lambda_function.zip lambda_function.py

    En Windows, utilice la herramienta de compresión que prefiera para crear el archivo lambda_function.zip. Asegúrese de que el archivo lambda_function.py y las carpetas que contienen las dependencias estén en la raíz del archivo .zip.

También puede crear su paquete de implementación mediante un entorno virtual de Python. Consulte Uso de archivos .zip para funciones de Lambda en Python

Crear la función de Lambda

Ahora use el paquete de implementación que creó en el paso anterior para implementar la función de Lambda.

Console
Para crear la función (consola)

Para crear una función de Lambda con la consola, primero debe crear una función básica que contenga el código “Hola, mundo”. A continuación, reemplace este código por su propio código de función mediante la carga del archivo .zip que creó en el paso anterior.

Para garantizar que no se agote el tiempo de espera de la función cuando cifra archivos PDF de gran tamaño, debe configurar los ajustes de memoria y tiempo de espera de la función. El formato de registro de la función también se establece como JSON. Es necesario configurar los registros con formato JSON cuando se utiliza el script de prueba proporcionado para que pueda leer el estado de invocación de la función desde los registros de CloudWatch y confirmar que la invocación se llevó a cabo de forma correcta.

  1. Abra la página de Funciones en la consola de Lambda.

  2. Asegúrese de trabajar en la misma Región de AWS en la que creó el bucket de S3. Puede cambiar la región por medio de la lista desplegable de la parte superior de la pantalla.

    Imagen que muestra el menú desplegable de regiones en la consola de Lambda
  3. Elija Crear función.

  4. Elija Author from scratch (Crear desde cero).

  5. Bajo Basic information (Información básica), haga lo siguiente:

    1. En Function name (Nombre de la función), introduzca EncryptPDF.

    2. En Tiempo de ejecución, seleccione Python 3.12.

    3. En Arquitectura, elija x86_64.

  6. Adjunte el rol de ejecución que creó en el paso anterior de la siguiente manera:

    1. Expanda la sección Change default execution role (Cambiar el rol de ejecución predeterminado).

    2. Seleccione Usar un rol existente.

    3. En Rol existente, seleccione su rol (LambdaS3Role).

  7. Seleccione Creación de función.

Para cargar el código de la función (consola)
  1. En el panel Código fuente, elija Cargar desde.

  2. Elija un archivo .zip.

  3. Seleccione Cargar.

  4. En el selector de archivos, seleccione un archivo .zip y luego elija Abrir.

  5. Seleccione Guardar.

Configuación de la memoria y el tiempo de espera de la función (consola)
  1. Seleccione la pestaña Configuración de la función.

  2. En el panel Configuración general, seleccione Editar.

  3. Establezca la Memoria en 256 MB y el Tiempo de espera en 15 segundos.

  4. Seleccione Guardar.

Configuración del formato de registro (consola)
  1. Seleccione la pestaña Configuración de la función.

  2. Seleccione Herramientas de supervisión y operaciones.

  3. En el panel Configuración de registros, seleccione Editar.

  4. Para la configuración de registro, seleccione JSON.

  5. Seleccione Guardar.

AWS CLI
Para crear la función (AWS CLI)
  • Ejecute el siguiente comando desde el directorio que contiene el archivo lambda_function.zip. Para el parámetro region, reemplace us-east-2 por la región en la que creó los buckets de S3.

    aws lambda create-function --function-name EncryptPDF \ --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler \ --runtime python3.12 --timeout 15 --memory-size 256 \ --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-2 \ --logging-config LogFormat=JSON

Configuración de un desencadenador de Amazon S3 para invocar una función

Para que la función de Lambda se ejecute cuando carga un archivo al bucket de origen, debe configurar un desencadenador para la función. Puede configurar el desencadenador de Amazon S3 mediante la consola o la AWS CLI.

importante

Este procedimiento configura el bucket de S3 para invocar su función cada vez que se crea un objeto en el bucket. Asegúrese de configurar esto solo en el bucket de origen. Si la función de Lambda crea objetos en el mismo bucket que la invoca, la función se puede invocar de forma continua en un bucle. Esto puede provocar que se facturen cargos imprevistos en su Cuenta de AWS.

Console
Para configurar el desencadenador de Amazon S3 (consola)
  1. Abra la página Funciones de la consola de Lambda y elija la función (EncryptPDF).

  2. Elija Add trigger (Añadir disparador).

  3. Seleccione S3.

  4. En Bucket, seleccione el bucket de origen.

  5. En Tipos de eventos, seleccione Todos los eventos de creación de objetos.

  6. En Recursive invocation (Invocación recursiva), marque la casilla de verificación para confirmar que no se recomienda utilizar el mismo bucket de S3 para la entrada y la salida. Puede obtener más información sobre los patrones de invocación recursiva en Lambda en Patrones recursivos que provocan funciones de Lambda descontroladas en Serverless Land.

  7. Elija Agregar.

    Al crear un desencadenador mediante la consola de Lambda, Lambda crea automáticamente una política basada en recursos para conceder permiso al servicio que seleccione para invocar la función.

AWS CLI
Para configurar el desencadenador de Amazon S3 (AWS CLI)
  1. Agregue una política basada en recursos a la función que permita que el bucket de origen de Amazon S3 invoque la función al agregar un archivo. Una instrucción de política basada en recursos concede permisos a otros Servicios de AWS para invocar la función. Para conceder permisos a Amazon S3 para invocar la función, ejecute el siguiente comando de la CLI. Asegúrese de reemplazar el parámetro source-account por su propio ID de Cuenta de AWS y de utilizar su propio nombre de bucket de origen.

    aws lambda add-permission --function-name EncryptPDF \ --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" \ --source-arn arn:aws:s3:::amzn-s3-demo-bucket \ --source-account 123456789012

    La política que defina con este comando permite a Amazon S3 invocar la función solo cuando se lleva a cabo una acción en el bucket de origen.

    nota

    Si bien los nombres de los buckets de S3 son únicos a nivel mundial, cuando se utilizan políticas basadas en recursos, se recomienda aclarar que el bucket debe pertenecer a la cuenta. Esto sucede porque si elimina un bucket, es posible que otra Cuenta de AWS cree un bucket con el mismo Nombre de recurso de Amazon (ARN).

  2. Guarde el siguiente JSON en un archivo llamado notification.json. Cuando se aplica al bucket de origen, este JSON configura el bucket para enviar una notificación a la función de Lambda cada vez que se agrega un objeto nuevo. Reemplace el número de Cuenta de AWS y la Región de AWS en el ARN de la función de Lambda por su número de cuenta y su región.

    { "LambdaFunctionConfigurations": [ { "Id": "EncryptPDFEventConfiguration", "LambdaFunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:EncryptPDF", "Events": [ "s3:ObjectCreated:Put" ] } ] }
  3. Ejecute el siguiente comando de la CLI para aplicar la configuración de notificación del archivo JSON que creó al bucket de origen. Reemplace amzn-s3-demo-bucket por el nombre del bucket de origen.

    aws s3api put-bucket-notification-configuration --bucket amzn-s3-demo-bucket \ --notification-configuration file://notification.json

    Para obtener más información sobre el comando put-bucket-notification-configuration y la opción notification-configuration, consulte put-bucket-notification-configuration en la Referencia de comandos de la CLI AWS.

Antes de empezar, asegúrese de que Docker y la última versión de AWS SAMCLI estén instalados en su máquina de compilación.

  1. En el directorio del proyecto, copie y pegue el siguiente código en un nuevo archivo denominado template.yaml. Sustituya los nombres de los buckets del marcador de posición:

    • Para el bucket de origen, sustituya amzn-s3-demo-bucket por cualquier nombre que cumpla con las reglas de nomenclatura del bucket de S3.

    • Para el bucket de destino, reemplace amzn-s3-demo-bucket-encrypted por <source-bucket-name>-encrypted cuando <source-bucket> sea el nombre que escogió para el bucket de origen.

    AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: EncryptPDFFunction: Type: AWS::Serverless::Function Properties: FunctionName: EncryptPDF Architectures: [x86_64] CodeUri: ./ Handler: lambda_function.lambda_handler Runtime: python3.12 Timeout: 15 MemorySize: 256 LoggingConfig: LogFormat: JSON Policies: - AmazonS3FullAccess Events: S3Event: Type: S3 Properties: Bucket: !Ref PDFSourceBucket Events: s3:ObjectCreated:* PDFSourceBucket: Type: AWS::S3::Bucket Properties: BucketName: amzn-s3-demo-bucket EncryptedPDFBucket: Type: AWS::S3::Bucket Properties: BucketName: amzn-s3-demo-bucket-encrypted

    La plantilla AWS SAM define los recursos que crea para la aplicación. En este ejemplo, la plantilla define una función de Lambda con el tipo AWS::Serverless::Function y dos buckets de S3 con el tipo AWS::S3::Bucket. Los nombres de los buckets especificados en la plantilla son marcadores de posición. Antes de implementar la aplicación mediante AWS SAM, debe editar la plantilla para cambiar el nombre de los buckets por nombres únicos a nivel mundial que cumplan con las reglas de nomenclatura para los buckets de S3. Este paso se explica con más detalle en Implementación de los recursos mediante AWS SAM.

    La definición del recurso de la función de Lambda configura un desencadenador para la función mediante la propiedad del evento S3Event. Este desencadenador hace que se invoque la función cada vez que se crea un objeto en el bucket de origen.

    La definición de la función también especifica una política de AWS Identity and Access Management (IAM) que se adjuntará al rol de ejecución de la función. La política administrada de AWS AmazonS3FullAccess proporciona a su función los permisos que necesita para leer y escribir objetos en Amazon S3.

  2. Ejecute el comando a continuación en el directorio en el que guardó los archivos template.yaml, lambda_function.py y requirements.txt.

    sam build --use-container

    Este comando recopila los artefactos de compilación de la aplicación y los coloca en el formato y la ubicación adecuados para implementarlos. Con la opción --use-container, la función se crea dentro de un contenedor de Docker tipo Lambda. Lo usamos aquí para que no necesite tener Python 3.12 instalado en su máquina local para que la compilación funcione.

    Durante el proceso de compilación, AWS SAM busca el código de la función de Lambda en la ubicación que especificó con la propiedad CodeUri en la plantilla. En este caso, especificamos el directorio actual como la ubicación (./).

    Si hay un archivo requirements.txt, AWS SAM lo usa para recopilar las dependencias especificadas. De forma predeterminada, AWS SAM crea un paquete de implementación .zip con el código y las dependencias de la función. También puede optar por implementar la función como una imagen de contenedor mediante la propiedad PackageType.

  3. Para implementar la aplicación y crear los recursos de Lambda y Amazon S3 especificados en la plantilla de AWS SAM, ejecute el siguiente comando:

    sam deploy --guided

    El uso de la marca --guided significa que AWS SAM le mostrará instrucciones para guiarlo a lo largo del proceso de implementación. Para esta implementación, acepte las opciones predeterminadas pulsando Intro.

Durante el proceso de implementación, AWS SAM crea los siguientes recursos en su Cuenta de AWS:

  • Una pila de AWS CloudFormation llamada sam-app

  • Una función de Lambda con el nombre EncryptPDF

  • Dos buckets de S3 con los nombres que eligió cuando editó el archivo de plantilla template.yaml de AWS SAM

  • Un rol de ejecución de IAM para la función con el formato de nombre sam-app-EncryptPDFFunctionRole-2qGaapHFWOQ8

Cuando AWS SAM termine de crear los recursos, debería ver el siguiente mensaje:

Successfully created/updated stack - sam-app in us-east-2

Probar la aplicación

Para probar la aplicación, cargue un archivo PDF en el bucket de origen y confirme que Lambda crea una versión cifrada del archivo en el bucket de destino. En este ejemplo, puede probarlo de forma manual mediante la consola o la AWS CLI o usando el script de prueba proporcionado.

Para las aplicaciones de producción, puede utilizar métodos y técnicas de prueba tradicionales, como las pruebas unitarias, para confirmar el correcto funcionamiento del código de la función de Lambda. La mejor práctica también es implementar pruebas como las del script de prueba proporcionado, que llevan a cabo pruebas de integración con recursos reales basados en la nube. Las pruebas de integración en la nube confirman que la infraestructura se desplegó correctamente y que los eventos fluyen entre los distintos servicios según lo esperado. Para obtener más información, consulte Cómo realizar pruebas de funciones y aplicaciones sin servidor.

Para probar la función de forma manual, agregue un archivo PDF a su bucket de origen de Amazon S3. Cuando agrega el archivo al bucket de origen, la función de Lambda se debe invocar de forma automática y debe almacenar una versión cifrada del archivo en el bucket de destino.

Console
Prueba de la aplicación cargando un archivo (consola)
  1. Para cargar un archivo PDF en el bucket de S3, haga lo siguiente:

    1. Abra la página Buckets de la consola de Amazon S3 y elija el bucket de origen.

    2. Seleccione Cargar.

    3. Elija Agregar archivos y utilice el selector de archivos para elegir el archivo PDF que desea cargar.

    4. Elija Abrir y, a continuación, Cargar.

  2. Compruebe que Lambda haya guardado una versión cifrada del archivo PDF en el bucket de destino, de la siguiente manera:

    1. Vuelva a la página Buckets de la consola de Amazon S3 y elija el bucket de destino.

    2. En el panel Objetos, ahora debería ver un archivo con el formato de nombre filename_encrypted.pdf (en el que filename.pdf es el nombre del archivo que cargó en el bucket de origen). Para descargar el PDF cifrado, seleccione el archivo y luego elija Descargar.

    3. Confirme que puede abrir el archivo descargado con la contraseña con la que lo protegió la función de Lambda (my-secret-password).

AWS CLI
Prueba de la aplicación cargando un archivo (AWS CLI)
  1. Desde el directorio que contiene el archivo PDF que desea cargar, ejecute el siguiente comando de la CLI: Reemplace el parámetro --bucket con el nombre del bucket de origen. Para los parámetros --key y --body, utilice el nombre de archivo del archivo de prueba.

    aws s3api put-object --bucket amzn-s3-demo-bucket --key test.pdf --body ./test.pdf
  2. Compruebe que la función creó una versión cifrada del archivo y la guardó en el bucket de S3 de destino. Ejecute el siguiente comando de la CLI, para ello reemplace amzn-s3-demo-bucket-encrypted por el nombre del bucket de destino.

    aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket-encrypted

    Si la función se ejecuta correctamente, verá un resultado similar al siguiente. El bucket de destino debe contener un archivo con el formato de nombre <your_test_file>_encrypted.pdf, en el que <your_test_file> es el nombre del archivo cargado.

    { "Contents": [ { "Key": "test_encrypted.pdf", "LastModified": "2023-06-07T00:15:50+00:00", "ETag": "\"7781a43e765a8301713f533d70968a1e\"", "Size": 2763, "StorageClass": "STANDARD" } ] }
  3. Para descargar el archivo que Lambda guardó en el bucket de destino, ejecute el siguiente comando de la CLI: Reemplace el parámetro --bucket con el nombre del bucket de destino. Para el parámetro --key, utilice el nombre de archivo <your_test_file>_encrypted.pdf, en el que <your_test_file> es el nombre del archivo de prueba que cargó.

    aws s3api get-object --bucket amzn-s3-demo-bucket-encrypted --key test_encrypted.pdf my_encrypted_file.pdf

    Este comando descarga el archivo en el directorio actual y lo guarda como my_encrypted_file.pdf.

  4. Confirme que puede abrir el archivo descargado con la contraseña con la que lo protegió la función de Lambda (my-secret-password).

Cree los siguientes archivos en el directorio del proyecto:

  • test_pdf_encrypt.py: es un script de prueba que puede usar para probar la aplicación de forma automática

  • pytest.ini: es un archivo de configuración para el script de prueba

Expanda las siguientes secciones para ver el código y obtener más información sobre la función de cada archivo.

Copie y pegue el siguiente código en un archivo denominado test_pdf_encrypt.py. Asegúrese de reemplazar los nombres de los buckets del marcador de posición:

  • En la función test_source_bucket_available, reemplace amzn-s3-demo-bucket por el nombre de su bucket de origen.

  • En la función test_encrypted_file_in_bucket, reemplace amzn-s3-demo-bucket-encrypted por source-bucket-encrypted, cuando source-bucket> sea el nombre del bucket de origen.

  • En la función cleanup, sustituya amzn-s3-demo-bucket por el nombre del bucket de origen y reemplace amzn-s3-demo-bucket-encrypted por el nombre del bucket de destino.

import boto3 import json import pytest import time import os @pytest.fixture def lambda_client(): return boto3.client('lambda') @pytest.fixture def s3_client(): return boto3.client('s3') @pytest.fixture def logs_client(): return boto3.client('logs') @pytest.fixture(scope='session') def cleanup(): # Create a new S3 client for cleanup s3_client = boto3.client('s3') yield # Cleanup code will be executed after all tests have finished # Delete test.pdf from the source bucket source_bucket = 'amzn-s3-demo-bucket' source_file_key = 'test.pdf' s3_client.delete_object(Bucket=source_bucket, Key=source_file_key) print(f"\nDeleted {source_file_key} from {source_bucket}") # Delete test_encrypted.pdf from the destination bucket destination_bucket = 'amzn-s3-demo-bucket-encrypted' destination_file_key = 'test_encrypted.pdf' s3_client.delete_object(Bucket=destination_bucket, Key=destination_file_key) print(f"Deleted {destination_file_key} from {destination_bucket}") @pytest.mark.order(1) def test_source_bucket_available(s3_client): s3_bucket_name = 'amzn-s3-demo-bucket' file_name = 'test.pdf' file_path = os.path.join(os.path.dirname(__file__), file_name) file_uploaded = False try: s3_client.upload_file(file_path, s3_bucket_name, file_name) file_uploaded = True except: print("Error: couldn't upload file") assert file_uploaded, "Could not upload file to S3 bucket" @pytest.mark.order(2) def test_lambda_invoked(logs_client): # Wait for a few seconds to make sure the logs are available time.sleep(5) # Get the latest log stream for the specified log group log_streams = logs_client.describe_log_streams( logGroupName='/aws/lambda/EncryptPDF', orderBy='LastEventTime', descending=True, limit=1 ) latest_log_stream_name = log_streams['logStreams'][0]['logStreamName'] # Retrieve the log events from the latest log stream log_events = logs_client.get_log_events( logGroupName='/aws/lambda/EncryptPDF', logStreamName=latest_log_stream_name ) success_found = False for event in log_events['events']: message = json.loads(event['message']) status = message.get('record', {}).get('status') if status == 'success': success_found = True break assert success_found, "Lambda function execution did not report 'success' status in logs." @pytest.mark.order(3) def test_encrypted_file_in_bucket(s3_client): # Specify the destination S3 bucket and the expected converted file key destination_bucket = 'amzn-s3-demo-bucket-encrypted' converted_file_key = 'test_encrypted.pdf' try: # Attempt to retrieve the metadata of the converted file from the destination S3 bucket s3_client.head_object(Bucket=destination_bucket, Key=converted_file_key) except s3_client.exceptions.ClientError as e: # If the file is not found, the test will fail pytest.fail(f"Converted file '{converted_file_key}' not found in the destination bucket: {str(e)}") def test_cleanup(cleanup): # This test uses the cleanup fixture and will be executed last pass

El script de prueba automatizado ejecuta tres funciones de prueba para confirmar el correcto funcionamiento de la aplicación:

  • La prueba test_source_bucket_available confirma que el bucket de origen se creó correctamente mediante la carga de un archivo PDF de prueba en el bucket.

  • La prueba test_lambda_invoked consulta el último flujo de registro de los registros de CloudWatch de la función para confirmar que la función de Lambda se ejecutó correctamente cuando cargó el archivo de prueba.

  • La prueba test_encrypted_file_in_bucket confirma que el bucket de destino contiene el archivo cifrado test_encrypted.pdf.

Una vez ejecutadas todas estas pruebas, el script ejecuta un paso de limpieza adicional para eliminar los archivos test.pdf y test_encrypted.pdf de los buckets de origen y destino.

Los nombres de los buckets especificados en este archivo son marcadores de posición, al igual que en la plantilla AWS SAM. Antes de ejecutar la prueba, debe editar este archivo con los nombres reales de los buckets de la aplicación. Este paso se explica con más detalle en Prueba de la aplicación con el script automatizado

Copie y pegue el siguiente código en un archivo denominado pytest.ini.

[pytest] markers = order: specify test execution order

Esto es necesario para especificar el orden en el que se ejecutan las pruebas del script test_pdf_encrypt.py.

Para ejecutar las pruebas, haga lo siguiente:

  1. Asegúrese de que el módulo pytest esté instalado en el entorno local. Puede instalar pytest ejecutando el siguiente comando:

    pip install pytest
  2. Guarde un archivo PDF con el nombre test.pdf en el directorio que contiene los archivos test_pdf_encrypt.py y pytest.ini.

  3. Abra un programa de terminal o intérprete de comandos y ejecute el siguiente comando desde el directorio que contiene los archivos de prueba:

    pytest -s -v

    Cuando concluya la prueba, la salida debe tener el siguiente aspecto:

    ============================================================== test session starts ========================================================= platform linux -- Python 3.12.2, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3 cachedir: .pytest_cache hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/home/pdf_encrypt_app/.hypothesis/examples') Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type> rootdir: /home/pdf_encrypt_app, configfile: pytest.ini plugins: anyio-3.7.1, hypothesis-6.70.0, localserver-0.7.1, random-order-1.1.0 collected 4 items test_pdf_encrypt.py::test_source_bucket_available PASSED test_pdf_encrypt.py::test_lambda_invoked PASSED test_pdf_encrypt.py::test_encrypted_file_in_bucket PASSED test_pdf_encrypt.py::test_cleanup PASSED Deleted test.pdf from amzn-s3-demo-bucket Deleted test_encrypted.pdf from amzn-s3-demo-bucket-encrypted =============================================================== 4 passed in 7.32s ==========================================================

Pasos a seguir a continuación

Ahora que creó esta aplicación de ejemplo, puede usar el código proporcionado como base para crear otros tipos de aplicaciones de procesamiento de archivos. Modifique el código del archivo lambda_function.py para implementar la lógica de procesamiento de archivos para su caso de uso.

Muchos casos de uso típicos del procesamiento de archivos implican el procesamiento de imágenes. Cuando se usa Python, las bibliotecas de procesamiento de imágenes más populares, como pillow, suelen contener componentes de C o C++. Para garantizar que el paquete de implementación de la función sea compatible con el entorno de ejecución de Lambda, es importante utilizar la distribución binaria de origen correcta.

Cuando implemente los recursos con AWS SAM, debe tomar algunas medidas adicionales para incluir la distribución de origen correcta en el paquete de implementación. Como AWS SAM no instalará dependencias para una plataforma diferente a la de la máquina de compilación, especificar la distribución de origen (archivo .whl) correcta en su archivo requirements.txt no funcionará si la máquina de compilación usa un sistema operativo o una arquitectura diferente del entorno de ejecución de Lambda. En su lugar, lleve a cabo una de las siguientes acciones: