From 17e88d5cbb9dda9cdc40c33ad9f35ee71a469a2c Mon Sep 17 00:00:00 2001 From: Fred Pauchet Date: Wed, 12 Feb 2020 22:36:45 +0100 Subject: [PATCH] adds a bunch of tools, 12 factors, virtual envs, administration and core concepts --- adoc/bonus/code-snippets.adoc | 10 ++++++++ adoc/main.adoc | 12 ++++++++- adoc/models/admin.adoc | 16 ++++++++---- adoc/toolchain/12-factors.adoc | 39 ++++++++++++++++++++++++++++++ adoc/toolchain/deps.adoc | 0 adoc/toolchain/external_tools.adoc | 2 +- adoc/toolchain/index.adoc | 6 ----- adoc/toolchain/terminology.adoc | 0 adoc/toolchain/venvs.adoc | 7 +++++- 9 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 adoc/bonus/code-snippets.adoc create mode 100644 adoc/toolchain/12-factors.adoc delete mode 100644 adoc/toolchain/deps.adoc delete mode 100644 adoc/toolchain/index.adoc delete mode 100644 adoc/toolchain/terminology.adoc diff --git a/adoc/bonus/code-snippets.adoc b/adoc/bonus/code-snippets.adoc new file mode 100644 index 0000000..72ea2e9 --- /dev/null +++ b/adoc/bonus/code-snippets.adoc @@ -0,0 +1,10 @@ +=== Snippets utiles (et forcément dispensables) + +==== Récupération du dernier tag Git en Python + +L'idée ici est simplement de pouvoir afficher le numéro de version ou le hash d'exécution du code, sans avoir à se connecter au dépôt. Cela apporte une certaine transparence, *sous réserve que le code soit géré par Git*. Si vous suivez scrupuleusement les 12 facteurs, la version de l'application déployée n'est plus sensée conserver un lien avec votre dépôt d'origine... Si vous déployez votre code en utilisant un `git fetch` puis un `git checkout `, le morceau de code ci-dessous pourra vous intéresser :-) + +[source,python] +---- + +---- diff --git a/adoc/main.adoc b/adoc/main.adoc index feb5107..0775ec7 100644 --- a/adoc/main.adoc +++ b/adoc/main.adoc @@ -21,19 +21,29 @@ Bonne lecture. == Environnement de travail +include::toolchain/12-factors.adoc[] + include::toolchain/venvs.adoc[] include::toolchain/tools.adoc[] +include::toolchain/external_tools.adoc[] + == Déploiement Et sécurisation du serveur. include::deploy/index.adoc[] +include::deploy/centos.adoc[] + == Modélisation include::models/admin.adoc[] == Go Live ! -Et supervision. \ No newline at end of file +Et supervision. + +== En bonus + +include::tools/code-snippets.adoc[] diff --git a/adoc/models/admin.adoc b/adoc/models/admin.adoc index 7854a33..ca18b06 100644 --- a/adoc/models/admin.adoc +++ b/adoc/models/admin.adoc @@ -4,7 +4,9 @@ Dans ce chapitre, on va parler de plusieurs concepts utiles au développement ra === Modélisation -On va aborder la modélisation des objets en elle-même, qui s'apparente à la conception de la base de données. Django utilise un modèle https://fr.wikipedia.org/wiki/Mapping_objet-relationnel[ORM] - c'est-à-dire que chaque objet peut s'apparenter à une table SQL, mais en ajoutant une couche propre au paradigme orienté objet. Il sera ainsi possible de définir facilement des notions d'héritage (tout en restant dans une forme d'héritage simple), la possibilité d'utiliser des propriétés spécifiques, des classes intermédiaires, ... +On va aborder la modélisation des objets en elle-même, qui s'apparente à la conception de la base de données. + +Django utilise un modèle https://fr.wikipedia.org/wiki/Mapping_objet-relationnel[ORM] - c'est-à-dire que chaque objet peut s'apparenter à une table SQL, mais en ajoutant une couche propre au paradigme orienté objet. Il sera ainsi possible de définir facilement des notions d'héritage (tout en restant dans une forme d'héritage simple), la possibilité d'utiliser des propriétés spécifiques, des classes intermédiaires, ... L'avantage de tout ceci est que tout reste au niveau du code. Si l'on revient sur la méthodologie des douze facteurs, ce point concerne principalement la minimisation de la divergence entre les environnements d'exécution. Déployer une nouvelle instance de l'application pourra être réalisé directement à partir d'une seule et même commande, dans la mesure où *tout est embarqué au niveau du code*. @@ -13,7 +15,9 @@ Assez de blabla, on démarre ! === Migrations -Les migrations (comprendre les "migrations du schéma de base de données") sont intimement liées à la représentation d'un contexte fonctionnel. L'ajout d'une nouvelle information, d'un nouveau champ ou d'une nouvelle fonction s'accompagne souvent/parfois de tables de données à mettre à jour, de champs étendre. +Les migrations (comprendre les "migrations du schéma de base de données") sont intimement liées à la représentation d'un contexte fonctionnel. L'ajout d'une nouvelle information, d'un nouveau champ ou d'une nouvelle fonction peut s'accompagner de tables de données à mettre à jour ou de champs à étendre. + +Toujours dans une optique de centralisation, les migrations sont directement embarquées au niveau du code. Le développeur s'occupe de créer les migrations en fonction des actions à entreprendre; ces migrations peuvent être retravaillées, _squashées_, ... et feront partie intégrante du processus de mise à jour de l'application. @@ -23,9 +27,11 @@ Woké. On va commencer par la *partie à ne _surtout_ (__surtout__ !!) pas faire C'est faux. -L'administration est une sorte de tour de contrôle évoluée; en se basant sur un modèle de données programmé et construit dynamiquement les formulaires associés. Elle joue avec les clés primaires, étrangères et les champs et types de champs par https://fr.wikipedia.org/wiki/Introspection[introspection]. Elle peut être configurée, mais dans un périmètre relativement restreint; quoi que vous fassiez, il y a un moment où la courbe de paramétrage sera tellement ardue que vous aurez plus facile à développer ce nouveau concept en utilisant les autres concepts de Django. +L'administration est une sorte de tour de contrôle évoluée; elle se base sur le modèle de données programmé et construit dynamiquement les formulaires qui lui est associé. Elle joue avec les clés primaires, étrangères, les champs et types de champs par https://fr.wikipedia.org/wiki/Introspection[introspection]. -Elle doit rester dans les mains d'administrateurs ou de gestionnaires, et dans leurs mains à eux uniquement. Il n'est pas question de donner des droits à des utilisateurs lambda. Indépendamment de la manière dont vous allez l'utiliser et la configurer, vous finirez malgré tout par devoir développer une "vraie" application, destinée aux utilisateurs classiques, et répondant à leurs besoins uniquement. +Son problème est qu'elle présente une courbe d'apprentissage asymptotique. Il est *très* facile d'arriver rapidement à un bon résultat, au travers d'un périmètre de configuration relativement restreint. Mais quoi que vous fassiez, il y a un moment où la courbe de paramétrage sera tellement ardue que vous aurez plus facile à développer ce que vous souhaitez ajouter en utilisant les autres concepts de Django. -Une bonne idée consiste à développer l'administration dans un premier temps, en *gardant en tête qu'il sera nécessaire de développer des concepts spécifiques*. Dans cet objectif, l'administration est un outil exceptionel, qui permet de valider un modèle, créer des objets rapidement et vérifier les liens qui existent entre eux. +Elle doit rester dans les mains d'administrateurs ou de gestionnaires, et dans leurs mains à eux uniquement: il n'est pas question de donner des droits aux utilisateurs finaux (même si c'est extrêment tentant durant les premiers tours de roues). Indépendamment de la manière dont vous allez l'utiliser et la configurer, vous finirez par devoir développer une "vraie" application, destinée aux utilisateurs classiques, et répondant à leurs besoins uniquement. + +Une bonne idée consiste à développer l'administration dans un premier temps, en *gardant en tête qu'il sera nécessaire de développer des concepts spécifiques*. Dans cet objectif, l'administration est un outil exceptionel, qui permet de valider un modèle, de créer des objets rapidement et de valider les liens qui existent entre eux. C'est un excellent outil de prototypage et de preuve de concept. diff --git a/adoc/toolchain/12-factors.adoc b/adoc/toolchain/12-factors.adoc new file mode 100644 index 0000000..f9e9b3d --- /dev/null +++ b/adoc/toolchain/12-factors.adoc @@ -0,0 +1,39 @@ +=== Méthodologie de travail + +Pour la méthode de travail et de développement, on va se baser sur les https://12factor.net/fr/[The Twelve-factor App] - ou plus simplement les *12 facteurs*. + +L'idée derrière cette méthode consiste à pousser les concepts suivants (repris grossièrement de la https://12factor.net/fr/[page d'introduction] : + +. Faciliter la mise en place de phases d'automatisation; plus simplement, faciliter les mises à jour applicatives, simplifier la gestion de l'hôte, diminuer la divergence entre les différents environnements d'exécution et offrir la possibilité d'intégrer le projet dans un processus d'https://en.wikipedia.org/wiki/Continuous_integration[intégration continue]/https://en.wikipedia.org/wiki/Continuous_deployment[déploiement continu] +. Faciliter la mise à pied de nouveaux développeurs ou de personnes souhaitant rejoindre le projet. +. Faciliter +. Augmenter l'agilité générale du projet, en permettant une meilleure évolutivité architecturale et une meilleure mise à l'échelle - _Vous avez 5000 utilisateurs en plus? Ajoutez un serveur et on n'en parle plus ;-)_. + +En pratique, les idées planquées derrière les quelques phrases ci-dessus permettront de monter facilement un nouvel environnement - qu'il soit sur la machine du petit nouveau ou sur un serveur Azure, Heroku, Digital Ocean ou votre nouveau Raspberry Pi Zéro caché à la cave. + +Pour reprendre de manière très brute les différentes idées derrière cette méthode, on a: + +NOTE: pensez à retravailler la partie ci-dessous; la version anglophone semble plus compréhensible... :-/ + +. Une base de code suivie avec un système de contrôle de version, plusieurs déploiements +. Déclarez explicitement et isolez les dépendances +. Stockez la configuration dans l’environnement +. Traitez les services externes comme des ressources attachées +. Séparez strictement les étapes d’assemblage et d’exécution +. Exécutez l’application comme un ou plusieurs processus sans état +. Exportez les services via des associations de ports +. Grossissez à l’aide du modèle de processus +. Maximisez la robustesse avec des démarrages rapides et des arrêts gracieux +. Gardez le développement, la validation et la production aussi proches que possible +. Traitez les logs comme des flux d’évènements +. Lancez les processus d’administration et de maintenance comme des one-off-processes + +.Concrètement +|=== +|Concept |Outil |Description +|Base de code suivie avec un système de contrôle de version| Git, Mercurial, SVN, ...|Chaque déploiement démarre à partir d'une base de code unique. Il n'y pas de dépôt "Prod", "Staging" ou "Dev". Il n'y en a qu'un et un seul. +|Déclaration explicite et isolation des dépendances| Pyenv, environnements virtuels, RVM, ...|Afin de ne pas perturber les dépendances systèmes, chaque application doit disposer d'un environnement sain par défaut. +|Configuration dans l'environnement| Fichiers .ENV| Toute clé de configuration (nom du serveur de base de données, adresse d'un service Web externe, clé d'API pour l'interrogation d'une ressource, ...) sera définie directement au niveau de l'hôte - à aucun moment, on ne doit trouver un mot de passe en clair dans le dépôt source ou une valeur susceptible d'évoluer, écrite en dur dans le code. +|Services externes = ressources locales| Fichiers .ENV| Chaque ressource doit pouvoir être interchangeable avec une autre, sans modification du code source. La solution consiste à passer toutes ces informations (nom du serveur et type de base de données, clé d'authentification, ...) directement via des variables d'environnement. +|Bien séparer les étapes de construction des étapes de mise à disposition| Capistrano, Gitea, un serveur d'artefacts, ...| L'idée est de pouvoir récupérer une version spécifique du code, sans que celle-ci ne puisse avoir été modifiée. Git permet bien de gérer des versions (au travers des tags), mais ces éléments peuvent sans doute être modifiés directement au travers de l'historique. +| diff --git a/adoc/toolchain/deps.adoc b/adoc/toolchain/deps.adoc deleted file mode 100644 index e69de29..0000000 diff --git a/adoc/toolchain/external_tools.adoc b/adoc/toolchain/external_tools.adoc index b8b5965..37ad721 100644 --- a/adoc/toolchain/external_tools.adoc +++ b/adoc/toolchain/external_tools.adoc @@ -1,4 +1,4 @@ -### graphviz +=== graphviz En utilisant django_extensions (! bien suivre les étapes d'installation !). diff --git a/adoc/toolchain/index.adoc b/adoc/toolchain/index.adoc deleted file mode 100644 index 2f9791b..0000000 --- a/adoc/toolchain/index.adoc +++ /dev/null @@ -1,6 +0,0 @@ - -== Configuration de l'environnement - -Et configuration de l'espace de travail. - - diff --git a/adoc/toolchain/terminology.adoc b/adoc/toolchain/terminology.adoc deleted file mode 100644 index e69de29..0000000 diff --git a/adoc/toolchain/venvs.adoc b/adoc/toolchain/venvs.adoc index 9aaa9f3..001cd06 100644 --- a/adoc/toolchain/venvs.adoc +++ b/adoc/toolchain/venvs.adoc @@ -5,4 +5,9 @@ On va commencer avec la partie la moins funky, mais la plus utile, dans la vie d Il est tout à fait possible de s'en passer complètement dans le cadre de "petits" projets ou d'applications déployées sur des machines dédiées, et de fonctionner à grand renforts de "sudo" et d'installation globale des dépendances. Cette pratique est cependant fortement déconseillée pour plusieurs raisons: . Pour la reproductibilité d'un environnement spécifique. Cela évite notamment les réponses type "Ca juste marche chez moi", puisqu'on a la possibilité de construire un environnement sain et appliquer des dépendances identiques, quelle que soit la machine hôte. -. il est tout à fait envisagable que deux applications soient déployées sur un même hôte, et nécessitent chacune deux versions différentes d'une même dépendance. \ No newline at end of file +. Il est tout à fait envisagable que deux applications soient déployées sur un même hôte, et nécessitent chacune deux versions différentes d'une même dépendance. + +> But it works on my machine! Then, we'll ship your machine. +> --A famous meme, And this is how Docker was born. + +