AWS Lambda CI pipeline con DGoss e TravisCI
Ho recentemente parlato di come sviluppare funzioni AWS Lambda offline, utilizzando le immagini docker di LambdaCI. Partendo dall’ambiente di sviluppo Python utilizzato per lo sviluppo di una funzione Lambda di esempio, vediamo come realizzare una pipeline di Continuous Integration che si occupi di verificarne il corretto funzionamento ad ogni nuovo commit. Utilizzeremo Goss come strumento di test e TravisCI per l’implementazione della pipeline di CI.
AWS Lambda in un container Docker
Vediamo rapidamente come eseguire una funzione AWS Lambda in un container Docker.
Utilizziamo la seguente funzione Python di esempio, che si occupa di processare dei messaggi accodati su SQS e che richiede un package (PILLOW) normalmente non presente nell’ambiente Lambda.
Per creare l’immagine docker necessaria all’esecuzione della nostra Lambda function, il relativo Dockerfile è il seguente, che partendo dall’immagine lambci/lambda:python3.6, consente l’installazione di eventuali pacchetti Python aggiuntivi previsti in requirements.txt
Consiglio di vedere questo post per maggiori dettagli; ora che abbiamo la nostra immagine Docker e la nostra Lambda function viene eseguita correttamente in un container, possiamo iniziare a realizzare la test suite.
Goss e DGoss
Ho scelto di utilizzare Goss come strumento di test principalmente per due motivi: grazie al wrapper DGoss è possibile interagire direttamente con un container docker sia per la fase di esecuzione dei test che durante lo sviluppo (o editing) degli stessi. Lo scopo principale di Goss è validare la configurazione di un server, che nel nostro caso è proprio il container che ospita la Lambda function. La suite di test può essere generata direttamente dallo stato corrente del server (o container) rendendo di fatto l’operazione molto veloce e pratica.
La definizione della test suite è basata su file YAML.
Procediamo molto rapidamente con l’installazione di Goss e DGoss e avviamo il container che ci permetterà di realizzare la test suite, utilizzando la sintassi Makefile.
Il comando avvia il container docker in modalità “STAY OPEN”, cioè avviando un API server in ascolto sulla porta 9001 e alla quale risponde la nostra funzione Lambda. Il parametro edit indica a DGoss che andremo ad utilizzare il container per la realizzazione della test suite. La directory test contatterà i file necessari all’esecuzione dei test stessi. Ad esempio, volendo verificare che la funzione processi correttamente i messaggi SQS, alcuni eventi di esempio (in formato JSON) saranno salvati in questa folder per essere poi utilizzati durante i test.
A questo punto possiamo utilizzare tutti i comandi di Goss per realizzare la nostra test suite: se vogliamo, per esempio, verificare la presenza del handler di funzione, si utilizza il comando:
goss add file /var/task/src/lambda_function.py
L’opzione ADD aggiunge un nuovo test al file di configurazione goss.yaml, nel nostro caso per verificare la presenza del file specificato. Goss consente di verificare moltissimi parametri di configurazione dell’ambiente in cui viene eseguito, come la presenza di file, pacchetti, processi, risoluzione dns, ecc. Il relativo manuale è molto esaustivo.
Realizziamo ora uno script che ci consenta di verificare la risposta della nostra funzione Lambda.
#!/bin/sh
# /var/task/test/test-script.sh
curl --data-binary "@/var/task/test/test-event.json" http://localhost:9001/2015-03-31/functions/myfunction/invocations
Utilizziamo curl per interrogare l’endpoint della nostra Lambda function inviando un evento SQS di test (il file test-event.json). Aggiungiamo quindi un ulteriore test Goss, questa volta di tipo command. Il file goss.yaml diventerà come il seguente.
La sezione command prevede l’esecuzione dello script che interroga la Lambda function. Ci aspettiamo su stdout un JSON dal contenuto specifico, che conferma la corretta esecuzione dalla funzione. Ovviamene questo test è solo un esempio esplicativo di ciò che può essere fatto con Goss.
Quanto abbiamo terminato le definizione della test suite, uscendo dal container (exit), DGoss si occuperà di copiare sul nostro host locale il file goss.yaml appena editato, in modo che persista dopo l’eliminazione del container stesso. Avviando nuovamente la procedura di edit, il file sarà copiato nel nuovo container e nuovamente sincronizzato al termine.
E’ arrivato il momento di eseguire il test! Al posto di edit, andremo semplicemente a specificare il comando run di DGoss.
DGoss si occupare di creare un nuovo container ed eseguire i test specificati. Di seguito un esempio.
Ottimo! La nostra test suite è pronta, procediamo ad integrarla nella nostra pipeline CI.
AWS Lambda CI in TravisCI
E’ arrivato il momento di configurare la pipeline CI. Ho scelto TravisCI per la sua semplicità e perché consente di effettuare la build di immagini docker gratuitamente. L’ho utilizzato anche in questo post con Ansible ed è tra gli strumenti di CI che preferisco. Per automatizzare il processi di test ad ogni commit andremo a configurare TravisCI per monitorare il repository GitHub/Bitbucket che ospita i sorgenti.
Un semplice file .travis.yaml realizza la pipeline.
Analizziamolo: la direttiva services indica a TravisCI di utilizzare il servizio docker. Prime di avviare i test, viene installato Goss/DGoss e viene effettuata la build della nostra immagine AWS Lambda, come specificato in before_install. Per ultimo, con script viene indicato il comando per l’effettiva esecuzione della test suite che abbiamo preparato in precedenza.
Ecco il risultato:
Fantastico! La nostra pipeline è realizzata!
Conclusioni
Ci siamo occupati di sviluppare e automatizzare il test di una semplice funzione AWS Lambda senza che questa sia mai realmente entrata nel cloud AWS: ho utilizzato questa modalità per alcuni progetti su cui ho lavorato e credo che permetta di velocizzare notevolmente lo sviluppo ed il mantenimento dei sorgenti, consentendo di effettuare il deployment su AWS di codice già testato e di qualità.
Questo repository GitHub raccoglie quanto trattato in questo articolo e può essere utilizzato come base di partenza per realizzare la propria pipeline CI con Goss.
Ci siamo divertiti? Alla prossima!