Serverless framework

Utilisation du framework Serverless

Dans le précédent post nous avons mis en place une API basé sur Lambda pour récupérer notre adresse IP publique. Si vous ne l’avez pas lu et que vous n’avez pas testé par vous même les fonctions Lambda je vous conseille de le lire d’abord.

La console AWS web est très pratique et permet de découvrir intuitivement la plupart des fonctions mais soyons honnête celà devient très vite fastidieux de développer ses fonctions en ligne et de cliquer pour déployer à chaque modification.

Heureusement pour nous il existe un framework, Serverless, qui est assez merveilleux et vous permet de coder sans vous soucier de toutes les étapes de publication. Cerise sur le gateau, il permet aussi de développer localement en simulant API Gateway et Lambda, cela vous permettra de coder/tester au fur et à mesure très pratique quand on débute 😍

Le but de ce post est de redéployer tout ce que nous avons fait au précédent post avec une seule commande, nous allons le déployer d’abord sur AWS puis localement.

Installer Serverless

C’est un cli NodeJS qui sera disponible pour tous les utilisateurs, il faut donc l’installer avec sudo

Avec Yarn :

1
sudo yarn global add serverless

Ou avec NPM :

1
sudo npm --global install serverless

Les crédentials AWS

Si vous avez au préalable installé aws cli, alors ces crédentials seront utilisés de manière transparente par Serverless. Je vous conseille tout de même de créer un compte dédié pour serverless. Après si vous vous en foutez vous pouvez passer à la section suivante pour gagner du temps, n’oubliez pas au moindre problème d’essayer un chmod -R 777 /.

D’une manière générale c’est une bonne pratique de multiplier les utilisateurs IAM pour chaque utilisation et les regrouper quitte à être trop permissif, dans notre cas nous allons être permissif et créer un profil admin avec droits d’automisation que nous pourrons revoir éventuellement plus tard. Il n’y a pas de schéma par défaut d’un profil IAM pour serverless (pour l’instant) et il faut avouer qu’il doit être bien costaud (Gestion S3, API Gateway, IAM, Lambda).

Dans la console web créez un utilisateur/rôle IAM, et settez le dans le cli avec :

1
serverless config credentials --provider aws --key xxxxxxxxxx --secret  xxxxxxxxxxxxx --profile serverless

Notez que cet accès est stocké avec le profil “serverless” que nous devrons spécifier par la suite dans la configuration.

Création de notre service serverless

Notre service va s’appeler myIP pour faire très original et ne pas rentrer en conflit avec monIP du post précédent.

Vous pouvez considérer les services serverless un peu comme un projet habituel, sauf que nous aurons tendances à découper en beaucoup de petit services une architecture Serverless.

Pour initier le service utilisez la commande suivante :

1
serverless create --template-url https://github.com/serverless/serverless/tree/master/lib/plugins/create/templates/aws-nodejs --path myIP

Modifications basiques

Configurons maintenant quelques points importants :

server.yml

Ajouter le bon profil d’utilisation IAM dans la section provider, et spécifiez la bonne région, sinon serverless va tout envoyer dans la région par défaut :

1
2
3
4
5
provider:
name: aws
runtime: nodejs8.10
profile: serverless
region: eu-west-1

Dans la section functions nous allons activer API Gateway :

1
2
3
4
5
6
7
functions:
hello:
handler: handler.hello
events:
- http:
path: /
method: get

handler.hs

On va le laisser tel quel pour l’instant :

1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict';
module.exports.hello = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
}),
};

// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};

On peut noter qu’on a utilisé LAMBDA-PROXY integration, ce qui permet au passage de chopper directement l’adresse IP de celui qui a lancé la requête.

Déploiement

Nous allons maintenant déployer et tester notre API :

1
serverless deploy

Et voilà c’est simplement déployé, vous n’avez plus qu’a faire un curl sur l’endpoint donnée par la dernière commande :

1
curl https://kwfxucs3zj.execute-api.eu-west-3.amazonaws.com/dev

Vous devez avoir un résultat qui ressemble à ça :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"message": "Go Serverless v1.0! Your function executed successfully!",
"input": {
"resource": "/",
"path": "/",
"httpMethod": "GET",
"headers": {
"Accept": "*/*",
"CloudFront-Forwarded-Proto": "https",
"X-Forwarded-Proto": "https"
},
"requestContext": {
"resourceId": "xvm7lgdfoc",
"resourcePath": "/",
"httpMethod": "GET",
"path": "/dev",
"accountId": "157438846073",
"protocol": "HTTP/1.1",
"stage": "dev",
"identity": {
"sourceIp": "90.118.158.37",
"userAgent": "curl/7.58.0",
},
"domainName": "kwfxucs3zj.execute-api.eu-west-3.amazonaws.com",
"apiId": "kwfxucs3zj"
},
}
}

J’ai volontaire nettoyé quelques trucs, mais on voit bien que ça marche 💪

Modifications pour récupérer l’ip

Ajoutons déjà une nouvelle fonction dans serverless.yml :

1
2
3
4
5
6
7
8
9
10
11
12
13
functions:
myIP:
handler: handler.myIP
events:
- http:
path: /ip
method: get
hello:
handler: handler.hello
events:
- http:
path: /
method: get

On modifie notre handler.js pour y ajouter la fonction :

1
2
3
4
5
6
7
8
module.exports.myIP = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
ip: event.requestContext.identity.sourceIp,
}),
};
};

Et on redéploie :

1
serverless deploy

Et bien sûr ça marche 💪 :

1
2
curl https://kwfxucs3zj.execute-api.eu-west-3.amazonaws.com/dev/ip
{"ip":"90.118.158.37"}

test en local

Le plus gros avantage de serverless, c’est de pouvoir tester nos fonctions en local via serverless-offline.

En bien sûr c’est simple comme bonjour !

Dans notre répertoire de service myIP

1
yarn init

Puis on installe serverless-offline

1
yarn add serverless-offline

On ajoute dans serverless.yml notre plugin serverless-offline :

1
2
plugins:
- serverless-offline

Y a plus qu’a lancer le serveur offline :

1
2
3
4
5
6
7
8
9
10
myIP$ serverless offline start
Serverless: Starting Offline: dev/eu-west-3.

Serverless: Routes for myIP:
Serverless: GET /ip

Serverless: Routes for hello:
Serverless: GET /

Serverless: Offline listening on http://localhost:3000

On teste :

1
2
curl http://localhost:3000/ip
{"ip":"127.0.0.1"}

Et voilà c’était du gateau 💪 !