Webux Lab

Par Studio Webux

Expérimentation avec SAM CLI de AWS

TG
Tommy Gingras Studio Webux S.E.N.C 2021-01-17

Introduction

Cet outil offert par AWS permet de créer des lambdas facilement et de tester le tout localement.

Ce tutoriel ne va pas en détail dans l’implémentation, je prend pour acquis que vous avez de bonne connaissance dans l’environnement AWS, docker et Linux/MacOS/Windows

Installation

Je vous recommande de suivre la documentation officielle, disponible ici : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-windows.html

Usage

Pour cet article, je vais utiliser Windows 10

Normalement j’utilise Mac OS, par contre c’est très similaire.

Donc pour le terminal, je vais utiliser PowerShell

Pour vous assurer que le tout est bien installé,

sam --version

Pour une démo / tutoriel avec du code offert par AWS : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html

Démo

Je n’ai malheureusement pas d’exemple concret à partager pour le moment. Voir les sources plus bas pour des exemples disponibles sur Github.

Voici ma structure:

C’est simplifié…

backend/
    lambda1/
        src/
            actions/
                get.js
                post.js
            index.js
        test/
            feature1.spec.js
        package.json
infrastructure/
    application.yaml
    db.yaml
    storage.yaml
    infra.yaml
    deploy-app.sh
    start-api.sh
layers/
    layer1/
        nodejs/
            package.json
    package.sh
utils/
    ci.js
frontend/
    index.html
package.json

Le fichier application.yaml contient la définition du API Gateway, des lambdas et de la layer.

Tout doit être dans le même fichier, car pour utiliser un seul API Gateway nous devons utiliser cette stratégie. De plus, la structure Monorepo facilite cette implémentation. Pour plus de détails / spécifications, demandez-moi dans les commentaires, ça va me faire plaisir de répondre

Puis les autres YAML contiennent la définition pour la base de données, la configuration du S3, et l’infrastructure (IAM, S3, et autres)

Ensuite le répertoire backend/ contient chaque lambda / service de l’application, le fichier index.js recoit la requête et chaque méthode est définie dans un fichier spécifique dans le répertoire src/actions/

La layer doit avoir cette structure (nodejs/) pour fonctionner. Les modules qui sont partagés peuvent facilement être ajouté dans la layer. Ou les dépendences qui ont une grande taille.

Le zip pour importer la lambda doit faire maximum 50MB et une fois extrait, la taille doit être maximum 250MB (vérifiez la documentation officielle, au cas où ça change, https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html)

Tester l’application localement

Structure simplifié du application.yaml

Ne pas copier/coller le yaml ci-dessous, il manque des informations ! C’est seulement pour donner une idée

Le CodeUri est le répertoire contenant le code source de la lambda

AWSApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      Name: !Ref ApiGatewayName
      StageName: !Ref ApiGatewayStageName
      EndpointConfiguration:
        Type: !Ref APIEndpointType
      TracingEnabled: !Ref APITracing
      Cors:
        AllowMethods: !Ref CorsMethods
        AllowHeaders: !Ref CorsHeaders
        AllowOrigin: !Ref CorsOrigin
        MaxAge: !Ref CorsMaxAge
        AllowCredentials: !Ref CorsAllowCredentials
      Auth:
        Authorizers:
          CognitoAuthorizer:
            UserPoolArn: "ARN..."
        InvokeRole: CALLER_CREDENTIALS
      Models:
        User:
          type: object
          required:
            - username
          properties:
            username:
              type: string
            refreshToken:
              type: string
            password:
              type: string
            name:
              type: string

AuthLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: auth-aws-auth
      CodeUri: ../backend/authentication/aws-auth
      Description: Authenticate the user using Cognito User Pool.
      Environment:
        Variables:
          COGNITO_POOL_ID: !Ref CognitoPoolId
          IDENTITY_POOL_ID: !Ref IdentityPoolId
          CLIENT_ID: !Ref CognitoClientId
      Events:
        Api:
          Type: Api
          Properties:
            Path: /auth
            Method: POST
            RestApiId: !Ref AWSApiGateway
            RequestModel:
              Model: User
              Required: true
      Policies:
        - AWSLambdaBasicExecutionRole
        - !Sub arn:aws:iam::${AWS::AccountId}:policy/Cognito-user

### Upload image to S3 Bucket
imageUploadLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: upload-aws-image-upload
      CodeUri: ../backend/upload/aws-image-upload
      Description: Upload an image to S3 Bucket
      Environment:
        Variables:
          S3_BUCKET_DATA: !Ref S3BucketData
          IDENTITY_POOL_ID: !Ref IdentityPoolId
          COGNITO_POOL_ID: !Ref CognitoPoolId
      Events:
        Api:
          Type: Api
          Properties:
            Path: /upload/image
            Method: POST
            RestApiId: !Ref AWSApiGateway
            Auth:
              Authorizer: CognitoAuthorizer
            RequestParameters:
              - method.request.header.Authorization:
                  Required: true
      Policies:
        - AWSLambdaBasicExecutionRole

Donc avec une configuration comme ci-dessus,

vous pouvez lancer :

cd infrastructure/

sam build -t application.yaml

Le résultat attendu

...

Build Succeeded

Built Artifacts  : .aws-sam\build
Built Template   : .aws-sam\build\template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Lancer le serveur local

sam local start-api --region "ca-central-1" \
    --parameter-override \
        param1=value1 \
        param2=value2

Le résultat attendu

...
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2021-01-17 16:06:00  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

Le premier coup, Docker va télécharger l’image pour faire en sorte que le tout fonctionne.

Par la suite, vous aller être en mesure de tester le code localement tout en utilisant les services AWS qui sont dans le cloud. Les messages vont apparaitre directement sur votre console et donc faciliter le développement.

Il faut garder en tête que quelques fonctionnalités ne sont pas 100% supportées en local. (voir la documentation officielle) J’ai eu plusieurs problèmes avec le API Gateway qui ne répondait pas comme le “vrai”. Ceci reste un excellent outil pour développer localement et plus rapidement.

Le code source est disponible dans le répertoire .aws-sam, pour appliquer les changements au code sans rebuild, vous pouvez modifier le code dans ce répertoire, les fichiers sont lus à chaque exécution, donc pas besoin de redémarrer le serveur.

IMPORTANT Les modifications effectuées dans .aws-sam sont écrasées à chaque build !

Sinon vous devez à chaque fois build et start-api. Ces deux actions deviennent longues quand il y a beaucoup de lambda dans le fichier application.yaml

Conclusion

Voici comment je testes localement mon application avec SAM CLI.

je vais ajouter plus de contenu au fur et à mesure que j’ajoutes de nouvelle fonctionnalitée.

Améliorations (To do)

Sources

Documentation officielle de AWS pour les lambdas, dynamoDB, SAM CLI, Layer et autres.

Il y a plusieurs exemples sur Github pour la structure,


Recherche