Crear una API con AWS y SAM
En esta publicación, vamos a crear una nueva aplicación que consta de una API que tiene un punto simple desarrollado en NodeJs y tiene un depósito S3. Toda la infraestructura de este proyecto se creará automáticamente utilizando SAM (AWS Serverless Application Model).
Preparar el ambiente
El primer paso es preparar el entorno de desarrollo instalando AWS CLI, SAM y NodeJs.
Para instalar la CLI de AWS simplemente siga los pasos explicados en el documento de AWS: Instalación o actualización de la última versión de la CLI de AWS. Confirme que lo ha instalado correctamente ejecutando:
> aws --version aws-cli/2.7.19 Python/3.9.11 Windows/10 exe/AMD64 prompt/off
Luego, para instalar AWS SAM sigamos los pasos explicados en el documento de AWS: Installing the AWS SAM CLI. Confirme que lo ha instalado correctamente ejecutando:
> sam --version SAM CLI, version 1.53.0
La instalación de Docker es opcional para SAM en este caso, pero es necesaria para probar algunos recursos de AWS. Por ejemplo, para ejecutar un Lambda localmente, necesitará Docker instalado.
Para las credenciales, crearemos una cuenta de AWS con access_key
y secret_access_key
, si no tiene estas credenciales, siga esta guía y cree un nuevo par de claves.
Finalmente, configuremos estas credenciales en nuestro entorno de desarrollo ejecutando:
> aws configure AWS Access Key ID [None]: your_access_key_id AWS Secret Access Key [None]: your_secret_access_key Default region name [None]: us-east-1 Default output format [None]: json
Puede encontrar más información sobre cómo configurar las credenciales aquí. las credenciales.
Codificando el proyecto
Ahora, comencemos con el código. Para este ejemplo vamos a usar NodeJS 16 pero el código de Lambda será tan simple que no va a importar mucho. Comience creando un nuevo proyecto con npm init
.
Dentro del proyecto creamos una nueva carpeta donde vamos a almacenar la función, que es realmente simple:
exports.handler = async (event, context) => { return { statusCode: 200, body: JSON.stringify({response: 'Success'}) } }
En esta carpeta también es necesario agregar otro archivo package.json
con el archivo Lambda como propiedad principal.
Ahora agreguemos el archivo template.yaml
que debe estar en la raíz, fuera de la carpeta de Lambda. La plantilla se verá así:
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: "AWS - Simple API with SAM" Resources: ### Role ### LambdaRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Path: "/" ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" Policies: - PolicyName: "AccessS3Bucket" PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - s3:PutObject - s3:GetObject Resource: "*" ### Bucket S3 ### SimpleBucket: Type: "AWS::S3::Bucket" Properties: BucketName: Fn::Join: ["-", [Ref: AWS::StackName, "simple-bucket"]] CorsConfiguration: CorsRules: - AllowedHeaders: - "*" AllowedMethods: - PUT AllowedOrigins: - "*" Id: Fn::Join: ["-", [Ref: AWS::StackName, "simple-bucket-cors-rule"]] MaxAge: 1800 ### Lambda ### SimpleLamdbaFunction: Type: AWS::Serverless::Function DependsOn: - LambdaRole Properties: Handler: app.handler CodeUri: ./simple-log Runtime: nodejs16.x Role: Fn::GetAtt: LambdaRole.Arn Events: HttpPost: Type: Api Properties: Path: '/simple-log' Method: post
Los cuatro valores iniciales son:
- AWSTemplateFormatVersion: la versión de la plantilla de Cloudformation. Actualmente,
2010–09–09
es la última versión y el único valor válido. Más sobre esto aquí. - Transform: Se utiliza para identificar la forma de procesar la plantilla. Más sobre esto aquí.
- Descripción: Un texto simple que describe el proyecto.
- Recursos: Vamos a declarar todos los recursos e infraestructura que necesitamos. Más sobre esto aquí.
Vamos a crear tres recursos:
- El papel de la Lambda. Este rol tiene los conceptos básicos de Lambda y las políticas para colocar y obtener objetos de cualquier depósito de S3 en la pila.
- El cubo S3.
- La lambda. Aquí definimos la ruta para realizar la solicitud, y la ruta y el nombre de la función a ejecutar. El rol de la función apuntará al ARN (Amazon Resource Names) del rol que definimos anteriormente.
Ahora estamos listos para construir e implementar la pila:
sam build ; sam deploy --guided
Como es la primera vez que implementamos el proyecto, es útil tener la implementación guiada, en cuyo caso tendremos que responder algunas preguntas a través de la línea de comando.
Una vez implementado, verifiquemos que todo se haya creado correctamente. Para probar la lambda, acceda a API Gateway
→ APIs
→ <Your api>
→ Dashboard
. Aquí, copie la URL para invocar la API. Me veré así:
https://<hashCode>.execute-api.<region>.amazonaws.com/Prod/
Luego, dentro de Resources
encontraremos el nuevo punto final con su ruta y método Http.
Ahora, verifiquemos la creación del depósito yendo a la sección S3 de la consola de AWS.
¡Funcionó perfectamente! Todos los recursos fueron creados y si queremos actualizarlos, todo lo que tenemos que hacer es compilarlo e implementarlo nuevamente.
Enlaces útiles
- Modelo de aplicación sin servidor de AWS
- Interfaz de línea de comandos de AWS
- ¿Qué es CloudFormation?
Si le interesa, puede echar un vistazo a algunos de los otros artículos que he escrito recientemente sobre Laravel: