Mes problèmes avec les déploiements AWS Lambda et comment je les ai résolus avec une CLI de base
Je m’amuse avec AWS Lambda ces derniers temps. Il est bon marché, facile à intégrer à d’autres services ou API, et presque sans effort pour être opérationnel. Presque. Comme je l’ai déjà noté dans un autre Publier, il n’y a pas d’option d’éditeur Web pour les fonctions Golang dans la console AWS. Au lieu de cela, il est nécessaire de construire un binaire, de créer une archive zip et de la télécharger sur la WebUI (cela devrait également être possible via CLI, je suppose).
D’accord pas de problème. Au début, j’ai juste saisi l’individu go build
et zip
commandes dans le terminal comme tout bonhomme. Malheureusement, alors que je commençais à m’intéresser de plus en plus à mes petites fonctions, j’ai commencé à empaqueter de nombreux programmes différents tout le temps. Bientôt, j’ai souhaité avoir quelque chose de plus organisé, alors j’ai créé ce script :
#!/bin/bash
filename=lambda-function-$(date +%Y_%m_%d).zip
GOOS=linux go build main.go
zip $filename main
J’ai été satisfait pendant un moment.
Bien sûr, la solution expliquée ci-dessus est assez décente pour le prototypage sporadique. Cependant, cet extrait doit résider dans le même répertoire que le point d’entrée de l’application pour rester pratique. J’ai dû faire beaucoup de copier/coller et me déplacer dans le système de fichiers. Je me suis lassé de ce mode opératoire : je voulais de l’argile malléable entre les mains, mais je n’avais qu’un bout de code rigide.
À ce stade, j’ai réalisé que j’avais besoin d’un nouvel utilitaire CLI pratique à mon actif, même si je savais que je ne devais pas aller trop loin et passer un week-end entier à concevoir quelque chose de trop fantaisiste. Pour commencer, j’ai rapidement rassemblé quelques exigences pour la CLI :
- il devrait créer un programme Go, puis le conditionner sous forme d’archive zip
- il devrait être écrit en Go (oui, allez jusqu’en bas !)
- il devrait permettre de sélectionner un répertoire cible n’importe où dans le système de fichiers
- il devrait permettre de personnaliser certaines balises de révision pour différencier différentes versions exécutables
- il doit comporter des valeurs par défaut raisonnables afin qu’il puisse être exécuté sans spécifier d’arguments
Selon les points ci-dessus, j’avais besoin de deux fonctionnalités principales : l’accès aux arguments de la ligne de commande et l’interaction avec le shell. Heureusement, la bibliothèque standard de Go avait déjà couvert cela.
En général, la tâche de traitement des arguments de ligne de commande peut être facilement effectuée dans Go en appelant os.Args
. De cette manière, il est possible de renvoyer une liste de jetons de chaîne représentant les arguments de la ligne de commande (y compris le nom du programme en cours d’exécution) et de les utiliser. Cependant, chaque CLI décente peut modifier ses options et modifier le comportement par défaut. Par exemple, je voulais exécuter mon utilitaire à partir de n’importe quel répertoire avec une commande comme celle-ci :
$ gozip --target path/to/main.go --revision v1_3_7
Frapper une fois en entrant juste le gozip
commande devrait également être possible, donc aucune option ne devrait être obligatoire. Bien sûr, gérer les options et les valeurs par défaut à partir de zéro c’est possible, mais la bibliothèque standard Go offre quelque chose de plus pratique : le flag
forfait. Comme le nom le suggère, flag
vous permet de configurer facilement les indicateurs de ligne de commande. Voici à quoi ressemble le code :
Assez simple, n’est-ce pas ? Une autre fonctionnalité intéressante de flag
est qu’il génère automatiquement une documentation utile pour la CLI :
$ gozip -h Usage of gozip: -name string name of the executable aws-lambda handler (default "main") -output string The desired path to store the zip archive. If not explicitly set, gozip tries to create a sub-directory at the target location -revision string a version number for the executable. If not explicitly set, gozip uses the current datetime -target string path to the Go program (default ".")
Maintenant que j’avais un moyen de capturer mon entrée et de la traiter, empaqueter un programme Go est devenu une question de vérifier correctement si les arguments d’option étaient des chemins de fichier valides (un travail pour os.Stat()
) et en interagissant avec la ligne de commande pour créer et compresser le programme. Comme mentionné ci-dessus, je ne voulais pas être entraîné dans le terrier du lapin de recréer mon utilitaire zip – bien que cela puisse être un exercice intéressant en soi – et je voulais continuer à tirer parti des capacités natives de Go. Notre ami os/exec
vient rapidement à la rescousse ici:
exec.Command("go", "build", "main.go")
De cette façon, gozip
agit comme un wrapper de terminal, donc je peux directement soumettre des commandes au shell, et il n’est pas nécessaire de reconstruire quoi que ce soit à partir de zéro.
Toutes les différentes pièces étaient prêtes, donc les assembler était simple à ce stade :
Il existe potentiellement de nombreuses extensions utiles qui pourraient être faites pour améliorer gozip
, comme la connexion aux registres Docker ou aux compartiments S3, l’ajout de la prise en charge de langues supplémentaires et même le développement d’une intégration de bout en bout avec AWS Lambda. Pour l’instant, je suis satisfait de ce que j’ai, étant donné qu’il a fallu un temps de développement négligeable et qu’il évitera sûrement quelques maux de tête à l’avenir.
Dans cet article, j’ai parlé de mes problèmes avec les déploiements AWS Lambda et comment je les ai résolus avec une CLI de base qui exploite le flag
et os/exec
packages dans la bibliothèque standard de Golang. Bien que des améliorations et des extensions supplémentaires rendraient mon utilité beaucoup plus précieuse, je pense avoir atteint un bon compromis entre une efficacité accrue et un effort de développement.
Avez-vous des outils utilitaires préférés ? Discutons-en !