Dans cette article, nous allons créer une fonction lambda en java, et l'intégrer à la pipeline de déploiement.
Voir aussi :
Lambda en javaTable of contents generated with markdown-toc
Cet article fait suite à la [partie 1][https://joseph-mbimbi.fr/blog/serverless-cicd-demo-1].
Le code est disponible à l'url suivante: https://github.com/mbimbij/aws-serverless-cicd-demo
Dans celui-ci, nous allons :
Ceci correspondant aux étapes 1.2 et 1.3 de l'implémentation de la pipeline.
Pour rappel, voici le résultat final que l'on souhaite obtenir:

Les étapes que l'on avait défini pour y arriver:

Et les sous-étapes de l'étape #1 :
Lambda en JavaCet article correspond donc à l'implémentation des étapes 1.2 et 1.3 .
Lambda en javastep1.1.6_codepipeline-projectstep1.2_add-java-lambda-functionNous créons un projet java dans le répertoire qui ne contenait précédemment que le template CloudFormation.
Nou ajoutons le handler Lambda suivant :
@Slf4j
public class HelloHandler implements RequestHandler<Object,HelloResponse> {
public final static String RESPONSE = "hello - v1";
@Override
public HelloResponse handleRequest(Object helloRequest, Context context) {
log.info(RESPONSE);
return new HelloResponse(RESPONSE);
}
}
Comme vous pouvez le voir, il s'agit du code applicatif le plus minimal qui soit, le point central de cet article étant la pipeline de déploiement.
On aurait pu renvoyer une Map, ça aurait été encore plus simple, mais bon, le code avait deja été produit, les tags placés, donc on fait avec.
Nous allons utiliser SAM pour gérer le déploiement de cette lambda. SAM est une surcouche à CloudFormation pour gérer des applications serverless.
Plus d'information disponible ici https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html
Voici le template que l'on utilisera:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: AWS lambda for auto-formation purpose.
Resources:
MainFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: target/aws-serverless-cicd-demo-1.0-SNAPSHOT.jar
Handler: com.example.HelloHandler
Runtime: java11
Description: Java function
FunctionName: aws-serverless-cicd-demo
MemorySize: 128
Timeout: 30
# Function's execution role
Policies:
- AWSLambdaBasicExecutionRole
- AWSLambdaReadOnlyAccess
- AWSXrayWriteOnlyAccess
- AWSLambdaVPCAccessExecutionRole
Tracing: Active
Description rapide:
Transform: indique qu'il s'agit d'un template SAM, et pas juste CloudFormationResources.MainFunction.CodeUri: la fonction lambda doit être packagée en .zip, pour NodeJS ou Python typiquement, ou .jar pour java. Ici ce paramètre indique le chemin relatif vers le jar contenant le code de la lambda. ça doit être un "fat-jar", avec toutes les dépendances incluesResources.MainFunction.Handler: le nom complet de la classe dans le jar contenant le handlerResources.MainFunction.Runtime: java11. Sont disponible aussi des runtimes NodeJS, Python, Go. On peut aussi créer un runtime custom si jamais on veut faire une fonction lambda pour un langage non supporté, tel que C++ ou Rust par exempleResources.MainFunction.MemorySize: Le nombre de MB alloué à la fonction. Détermine aussi la quantité de CPU allouéeResources.MainFunction.Timeout: Le timeout en secondesResources.MainFunction.Tracing: On active le tracing XRayResources.MainFunction.Policies: Les policies IAM attribuées à la fonction. On a repris ces rôles d'un précédent mini-projet, il semble y avoir plus de droits que nécessaire, mais tant pisNous allons déployer la fonction java via la CLI de SAM. SAM va uploader la fonction dans un bucket S3 et généré un nouveau template avec le CodeUri pointant vers l'emplacement S3.
Pour cela on propose 2 manières de procéder:
Tout d'abord, créez un bucket S3 ou récupérer le nom d'un bucket existant
Ensuite, on peut déployer en 3 commandes:
mvn clean package
sam package --template-file sam-template.yml --s3-bucket $BUCKET --output-template-file out-sam-template.yml
sam deploy --template-file out-sam-template.yml --stack-name serverless-cicd-demo-application --no-confirm-changeset --capabilities CAPABILITY_IAM
Ou alors en 2 commandes:
mvn clean package
sam deploy --template-file sam-template.yml --stack-name serverless-cicd-application-stack --capabilities CAPABILITY_IAM --no-confirm-changeset --s3-bucket $BUCKET
On peut aussi laisser SAM créer le bucket S3 tout seul:
mvn clean package
sam deploy --template-file sam-template.yml --stack-name serverless-cicd-application-stack --capabilities CAPABILITY_IAM --no-confirm-changeset --resolve-s3
step1.2_add-java-lambda-functionstep1.3.1_integrate-application-and-pipeline-buildAu cours de cette étape nous effectuons:
buildspec dans la déclaration de la ressource CodeBuild, qui va lancer sam package et va placer le résultat dans le bucket S3CodeBuild pour y mettre le nom du bucket, afin qu'il soit accessible lors de l'éxécution du buildCodeBuild pour les dépendances maven mettez à jour la stack de la pipeline, pousser le code et vérifier que le bucket du pipeline est bien alimenté avec le résultat de CodeBuild
à la fin de cette étape, nous avons la pipeline suivante:

step1.3.1_integrate-application-and-pipeline-buildstep1.3.2_simplest-deployDans cette étape, nous allons déployer l'application. Pour cela, nous allons récupérer la sortie de l'étape de build, soit le template SAM en sortie de sam package.
Nous allons rajouter une étape de déploiement au projet CodePipeline, pour cela nous rajoutons à la stack CloudFormation de la pipeline:
SAM car SAM => CloudFormationIAM attribué au déploiement CloudFormation du template SAMCodePipeline pour lui permettre de créer la stack SAMCodePipeline pour lui permettre d'attribuer le rôle CloudFormationRole au déploiement SAMCodepiplineà la fin de cette étape, nous avons la pipeline suivante:

step1.3.2_simplest-deploystep1.3.3_pre-traffic-hook-integration-testDans cette étape, nous rajoutons un test automatisé permettant de vérifier la nouvelle version de la fonction Lambda déployée.
Void https://github.com/aws/serverless-application-model/blob/master/docs/safe_lambda_deployments.rst en guise de référence.
Voici une illustration du processus:

Comme l'indique l'image, la pipeline va déployer une nouvelle version de la Lambda. Cependant, avant de rediriger le traffic vers cette version, nous avons configuré l'éxécution de tests automatisés. Si jamais les tests échouent, l'alias n'est pas repositionné sur la nouvelle version et le traffic n'est donc pas redirigé.
Pour réaliser cela nous avons effectué les ajouts et modifications suivantes:
SAM:
Les Lambdas de pre et post-traffic doivent avoir un nom en "CodeDeployHook_*", car pour les traffic hooks et les safe deployments, SAM va créer un projet CodeDeploy avec un rôle ayant la policy suivante:
{
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:*:*:function:CodeDeployHook_*",
"Effect": "Allow"
}
Ce qui n'est pas clairement documenté, et que j'ai découvert via une issue github du projet SAM.
Récapitulons, à la fin de cette étape, nous avons la pipeline suivante:

Dans cet article, nous sommes parti d'un embryon de pipeline ayant juste les stages "Source" et "Build".
Nous avons:
Lambda en java retournant en gros "hello-world"Dans le prochain article, au choix nous allons:
CloudFormation https://github.com/mbimbij/aws-serverless-cicd-demo