Cette suite d'ateliers de programmation (tutoriels pratiques à suivre à votre rythme) est destinée à aider les développeurs Google App Engine (standard) à moderniser leurs applications en les guidant tout au long d'une série de migrations. L'étape la plus importante est de délaisser les services groupés de l'environnement d'exécution d'origine, car les environnements d'exécution nouvelle génération sont plus souples et offrent aux utilisateurs davantage d'options de service. Le passage à l'environnement d'exécution nouvelle génération vous permet d'intégrer plus facilement les produits Google Cloud, d'utiliser une plus large gamme de services compatibles et de prendre en charge les versions de langage actuelles.
Ce tutoriel initial illustre les premières étapes de la migration vers le framework Web dans les applications App Engine: passer de webapp2
à Flask. Dans votre application, vous pouvez utiliser n'importe quel framework Web qui gère le routage, mais pour ce tutoriel, nous utilisons Flask car ce produit est largement utilisé par la communauté.
Vous apprendrez à effectuer les tâches suivantes :
- Utiliser des bibliothèques tierces (intégrées ou autre)
- Mettre à jour les fichiers de configuration
- Migrer une application simple depuis
webapp2
vers Flask
Prérequis
- Un projet Google Cloud Platform avec:
- Connaissances de base concernant Python
- Bonne connaissance des commandes Linux de base
- Des connaissances de base du développement et du déploiement d'applications App Engine
Enquête
Comment allez-vous utiliser cet atelier de programmation ?
Le framework webapp
a été regroupé à l'origine lorsque App Engine a été lancé sur Python 2.5 en 2008. Quelques années plus tard, il a été remplacé par son successeur webapp2
lorsque l'environnement d'exécution 2.7 a été abandonné en 2013.
Bien que webapp2
(voir les documents) soit toujours présent et puisse être utilisé en dehors d'App Engine en tant que framework Web compatible WSGI, il n'effectue pas par lui-même le routage des requêtes utilisateur vers le code approprié dans l'application. Il s'appuie à la place sur App Engine, les fichiers de configuration et le développeur pour acheminer le trafic Web vers les "gestionnaires" correspondants. Par ailleurs, les principaux avantages de webapp2
étant étroitement liés aux services groupés d'App Engine, ceci a pour effet de le rendre obsolète, même s'il fonctionne sur Python 3 (voir aussi problème lié).
Ce module offre aux professionnels une expérience pratique de la migration d'une application webapp2
simple vers Flask, un framework compatible avec App Engine, et des nombreux autres services en dehors de Google Cloud, qui améliorent considérablement la portabilité des applications. Si Flask n'est pas le framework souhaité pour déplacer votre application, vous pouvez en sélectionner un autre du moment qu'il effectue son propre routage. Cet atelier de programmation présente aux décideurs informatiques (ITDM) et aux développeurs les différentes étapes du processus de migration. Vous pouvez ainsi vous familiariser avec ce processus, quel que soit le framework vers lequel vous effectuez la migration.
Voici les principales étapes de cette migration:
- Configuration/Préparation
- Ajouter une bibliothèque tierce Flask
- Mettre à jour les fichiers de l'application
- Mettre à jour le fichier de modèle HTML
Avant de passer à la partie principale du tutoriel, nous allons configurer notre projet, obtenir le code, puis vous (re)familiariser avec la commande gcloud
et déployer l'application de base de façon à commencer avec un code fonctionnel.
1. Configurer le projet
En tant que développeur existant, le tableau de bord App Engine affiche probablement déjà les services que vous avez exécutés. Pour les besoins de ce tutoriel, nous vous recommandons de créer un projet ou de réutiliser un projet existant pour ce tutoriel. Assurez-vous que le projet dispose d'un compte de facturation actif et que App Engine (app) est activé.
2. Téléchargez l'application exemple de référence
Le dépôt de migration de GAE contient tout le code dont vous avez besoin. Clonez-le ou téléchargez son fichier ZIP. Pour ce tutoriel, vous allez commencer par le code situé dans le dossier (START) du Module 0, et lorsque vous aurez terminé le tutoriel, votre code devra correspondre à celui situé dans le dossier (FINISH) du Module 1. Si ce n'est pas le cas, vérifiez les différences de façon à passer à l'atelier suivant.
- START: Code du Module 0
- FINISH: Code du Module 1
- Dépôt complet (pour cloner ou télécharger un fichier ZIP)
Le dossier du Module 0 doit contenir des fichiers semblables à ceux illustrés par la commande POSIX ls
:
$ ls
app.yaml index.html main.py
3. (Re)Familiarisez-vous avec les commandes gcloud
Si la commande gcloud
n'existe pas encore sur votre ordinateur, installez le SDK Google Cloud et assurez-vous que gcloud
est présent dans le chemin d'exécution, puis familiarisez-vous avec les commandes gcloud
suivantes:
gcloud components update
: mettre à jour le SDK Google Cloudgcloud auth login
: se connecter à votre compte avec identifiantsgcloud config list
: répertorier les paramètres de configuration du projet GCPgcloud config set project PROJECT_ID
: définir l'ID du projet GCPgcloud app deploy
: déployer votre application App Engine
Si vous n'avez pas utilisé App Engine avec gcloud
récemment, vous devez exécuter les quatre premières commandes (1 à 4) avant de passer aux étapes suivantes. Découvrons-les rapidement.
Tout d'abord, gcloud components update
garantit que vous disposez de la dernière version du SDK Cloud. L'exécution de cette commande devrait produire un résultat semblable à celui-ci:
$ gcloud components update Your current Cloud SDK version is: 317.0.0 You will be upgraded to version: 318.0.0 ┌──────────────────────────────────────────────────┐ │ These components will be updated. │ ├──────────────────────────┬────────────┬──────────┤ │ Name │ Version │ Size │ ├──────────────────────────┼────────────┼──────────┤ │ Cloud SDK Core Libraries │ 2020.11.06 │ 15.5 MiB │ │ gcloud cli dependencies │ 2020.11.06 │ 10.6 MiB │ └──────────────────────────┴────────────┴──────────┘ The following release notes are new in this upgrade. Please read carefully for information about new features, breaking changes, and bugs fixed. The latest full release notes can be viewed at: https://cloud.google.com/sdk/release_notes 318.0.0 (2020-11-10) . . . (release notes) . . . Subscribe to these release notes at https://groups.google.com/forum/#!forum/google-cloud-sdk-announce. Do you want to continue (Y/n)? ╔════════════════════════════════════════════════════════════╗ ╠═ Creating update staging area ═╣ ╠════════════════════════════════════════════════════════════╣ ╠═ Uninstalling: Cloud SDK Core Libraries ═╣ ╠════════════════════════════════════════════════════════════╣ ╠═ Uninstalling: gcloud cli dependencies ═╣ ╠════════════════════════════════════════════════════════════╣ ╠═ Installing: Cloud SDK Core Libraries ═╣ ╠════════════════════════════════════════════════════════════╣ ╠═ Installing: gcloud cli dependencies ═╣ ╠════════════════════════════════════════════════════════════╣ ╠═ Creating backup and activating new installation ═╣ ╚════════════════════════════════════════════════════════════╝ Performing post processing steps...done. Update done! To revert your SDK to the previously installed version, you may run: $ gcloud components update --version 317.0.0
Ensuite, utilisez gcloud auth login
pour vous authentifier pour les commandes gcloud
que vous déclencherez:
$ gcloud auth login Your browser has been opened to visit: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id= . . . You are now logged in as [YOUR_EMAIL]. Your current project is [PROJECT_ID]. You can change this setting by running: $ gcloud config set project PROJECT_ID
Utilisez gcloud config list
pour afficher les paramètres actuels de votre projet:
$ gcloud config list [core] account = YOUR_EMAIL disable_usage_reporting = False project = PROJECT_ID Your active configuration is: [default]
La commande ci-dessus vous indique comment créer un projet ou sélectionner un projet existant. Si la sortie de gcloud config list
ne correspond pas au projet sélectionné que vous souhaitez utiliser pour ce tutoriel, exécutez gcloud config set project PROJECT_ID
pour définir l'ID du projet. Vérifiez ensuite que l'ID du projet est défini en exécutant à nouveau la commande gcloud config list
.
$ gcloud config set project PROJECT_ID Updated property [core/project].
Si vous préférez utiliser Cloud Console, vous pouvez suivre l'interface utilisateur pour créer un projet si vous le souhaitez ou utiliser un projet préexistant. Dans le tableau de bord de votre projet, vous devez voir la fiche info qui contient son ID (ainsi que le nom et le numéro du projet):
La dernière commande (5), gcloud app deploy
, sert à déployer votre application sur App Engine. Comme nous n'en sommes qu'au début, vous pouvez vous abstenir de déployer le code du Module 0 maintenant. Toutefois nous conseillons quand même de le faire pour vérifier qu'il fonctionne. Lors de l'exécution, sélectionnez la région géographique dans laquelle vous souhaitez exécuter l'application (généralement votre emplacement). Cependant, vous ne pourrez pas en changer une fois définie. Consultez ensuite les autres informations de déploiement. Une fois l'opération terminée, l'URL à laquelle votre application sera diffusée s'affiche. Voici une version abrégée de ce que vous pouvez voir:
$ gcloud app deploy Services to deploy: descriptor: [/private/tmp/mod0-baseline/app.yaml] source: [/private/tmp/mod0-baseline] target project: [PROJECT_ID] target service: [default] target version: [20201116t220827] target url: [https://PROJECT_ID.REG_ABBR.r.appspot.com] Do you want to continue (Y/n)? Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 1 file to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://PROJECT_ID.REG_ABBR.r.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
Si vous n'avez pas utilisé App Engine depuis un certain temps, vous remarquerez peut-être que la commande appcfg.py update
de déploiement initial a été remplacée par gcloud app deploy
. Pour en savoir plus sur gcloud app deploy
, consultez sa page de documentation.
Une autre modification récente est l'URL des applications déployées, passée de http://PROJECT_ID.appspot.com
à http://PROJECT_ID.REG_ABBR.r.appspot.com
. La plupart des applications seront finalement converties au nouveau format. Pour plus d'informations sur le format des URL, consultez la documentation sur les requêtes et le routage.
Une fois l'application déployée, actualisez le navigateur (plusieurs fois) pour voir les dernières visites:
S'il s'agit d'une nouvelle application, vous ne verrez qu'une ou quelques visites.
Le moteur d'exécution d'App Engine Python 2 fournit un ensemble de bibliothèques tierces intégrées qu'il vous suffit de spécifier dans votre fichier app.yaml
pour les utiliser. Bien que leur utilisation ne soit pas nécessaire avec cette migration, elles le seront pour le prochain tutoriel de migration (Module 2).
Les bibliothèques tierces qui ne sont pas intégrées doivent être spécifiées dans un fichier appelé requirements.txt
et installé localement dans le dossier lib
du même répertoire que le code de l'application où tout est importé dans App Engine. Pour plus d'informations, consultez la documentation sur le regroupement de bibliothèques tierces.
Les bibliothèques copiées telles que Flask nécessitent de demander à App Engine de les rechercher dans le dossier lib
à l'aide du fichier de configuration appengine_config.py
. Le fichier de configuration appengine_config.py
est placé dans le même dossier d'application de premier niveau que requirements.txt
et lib
. Dans cette partie du tutoriel, vous allez effectuer les opérations suivantes:
- Créer
requirements.txt
(précisez s'il s'agit d'une bibliothèque tierce copiée) - Créer
appengine_config.py
(reconnaissance des bibliothèques tierces) - Installer des packages et des dépendances tiers
1. Créer requirements.txt
Créez un fichier requirements.txt
pour spécifier vos packages. Dans notre cas, Flask est la bibliothèque tierce nécessaire. Au moment de la rédaction de cet article, la dernière version est la 1.1.2. Vous devez donc créer requirements.txt
avec cette ligne:
Flask==1.1.2
Pour en savoir plus sur les formats acceptés, consultez la documentation sur requirements.txt
.
2. Créer appengine_config.py
L'étape suivante consiste à faire en sorte qu'App Engine reconnaisse les bibliothèques tierces externes. Créez un fichier nommé appengine_config.py
avec le contenu suivant :
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Ce code effectue exactement ce que nous avons spécifié précédemment, c'est-à-dire qu'App Engine pointe vers le dossier lib
pour les bibliothèques copiées.
3. Installer les packages et les dépendances
Exécutez maintenant la commande pip install
pour créer le dossier lib
et y installer Flask, ainsi que ses dépendances:
$ pip install -t lib -r requirements.txt
Que vous utilisiez pip
ou pip2
, une fois l'installation du package terminée, vous devez créer un dossier lib
dont le contenu ressemble à ceci:
$ ls lib bin/ click/ click-7.1.2.dist-info/ flask/ Flask-1.1.2.dist-info/ itsdangerous/ itsdangerous-1.1.0.dist-info/ jinja2/ Jinja2-2.11.2.dist-info/ markupsafe/ MarkupSafe-1.1.1.dist-info/ werkzeug/ Werkzeug-1.0.1.dist-info/
Nous allons maintenant mettre à jour le fichier d'application, main.py
.
1. Importations
Les importations se présentent d'abord comme dans tous les fichiers Python. L'importation du framework webapp2
est suivie de la bibliothèque Datastore ndb
, et enfin de l'extension App Engine qui traite les modèles de style Django. La page suivante doit normalement s'afficher :
- AVANT :
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
Lorsque vous passez à Flask, vous importez en même temps les composants Flask et des éléments du moteur de rendu de modèles. Supprimez la paire d'importations associées à webapp2
et remplacez-la comme suit (laissez l'importation ndb
en l'état):
- APRÈS :
from flask import Flask, render_template, request
from google.appengine.ext import ndb
2. Démarrage
Les applications utilisant webapp2
nécessitent un seul tableau (liste Python) qui répertorie tous les routages et gestionnaires dans un fichier Python (il peut y en avoir d'autres):
- AVANT :
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
Gardez à l'esprit que app.yaml
effectue un routage de niveau supérieur et peut appeler différents gestionnaires. L'exemple d'application est suffisamment simple pour que toutes les routes parviennent au gestionnaire main.py
.
Flask n'utilise pas de tables de routage de ce type. Vous devez donc supprimer ces lignes dans main.py
. Flask requiert également une initialisation. Ajoutez donc la ligne suivante en haut de main.py
, juste sous les importations:
- APRÈS :
app = Flask(__name__)
Dans Flask, vous initialisez le framework, puis vous utilisez des décorateurs pour définir les routes. De plus, les routes sont associées à des fonctions, et non à des classes ou à des méthodes.
Nous vous invitons à prendre le temps de consulter le tutoriel Flask ainsi que la documentation Flask pour vous familiariser avec les fonctionnalités, car cela n'est pas inclus dans cet atelier de programmation.
3. Modèle de données
Aucune modification ici. Datastore sera au cœur de l'atelier de programmation suivant.
4. Gestionnaires
L'application, quel que soit le framework que vous utilisez (webapp2
ou Flask), effectue trois opérations:
- Gérer les requêtes GET de chemin racine (
/
) - Enregistrer une page Web "visite" (créer/stocker un objet
Visit
) - Afficher les 10 visites les plus récentes (avec un modèle prédéfini,
index.html
)
Le framework webapp2
utilise un modèle d'exécution basé sur la classe dans lequel les gestionnaires sont créés pour chaque méthode HTTP compatible. Dans notre cas simple, nous ne disposons que de GET
, donc une méthode get()
est définie:
- AVANT :
class MainHandler(webapp2.RequestHandler):
def get(self):
store_visit(self.request.remote_addr, self.request.user_agent)
visits = fetch_visits(10) or () # empty sequence if None
tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(tmpl, {'visits': visits}))
Comme mentionné ci-dessus, Flask effectue son propre routage. Au lieu d'une classe de gestionnaire, vous écrivez des fonctions et les décorez avec la route pour laquelle elles doivent être appelées. Les utilisateurs peuvent spécifier des méthodes HTTP gérées dans l'appel de décorateur, soit : @app.route('/app/', methods=['GET', 'POST'])
. Étant donné que la valeur par défaut est seulement GET
(et implicitement HEAD
), vous pouvez la laisser désactivée.
Lors de la migration vers Flask, remplacez la classe MainHandler
et sa méthode get()
par la fonction de routage Flask suivante:
- APRÈS :
@app.route('/')
def root():
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10) or () # empty sequence if None
return render_template('index.html', visits=visits)
Cet exemple n'est évidemment pas représentatif de votre application, qui sera probablement plus complexe. L'un des objectifs principaux de ces tutoriels est de vous aider à vous lancer, de créer une partie de cette "mémoire musculaire" et à déterminer où modifier le code spécifique à App Engine. Pour vérifier que vous avez effectué ces modifications correctement, comparez le vôtre avec main.py
du Module 1.
5. Fichiers auxiliaires
Aucune modification n'est à apporter au fichier .gcloudignore
. Il sert à spécifier les fichiers à ne pas déployer sur App Engine, qui ne sont pas nécessaires au déploiement et à l'exécution de l'application, y compris, mais sans s'y limiter, le fichier Python auxiliaire, le contrôle de la source, le code récurrent du dépôt, etc. Notre .gcloudignore
ressemble à ceci (les commentaires ont été supprimés par souci de concision):
.gcloudignore
.git
.gitignore
.hgignore
.hg/
*.pyc
*.pyo
__pycache__/
/setup.cfg
README.md
1. Déplacer le fichier de modèle
Dans le dossier du dépôt de référence (Module 0), le fichier de modèle index.html
se trouve dans le même dossier que les fichiers de l'application. Comme Flask requiert des fichiers HTML placés dans un dossier templates
, vous devez créer ce dossier (mkdir templates
) et y placer index.html
. Dans un système compatible POSIX, tel que Linux ou Mac OS X, les commandes seraient les suivantes:
mkdir templates
mv index.html templates
2. Mettre à jour le fichier de modèle
Une fois que vous avez déplacé index.html
dans templates
, il est temps de procéder à une modification légère, mais obligatoire. Examinons l'intégralité du fichier de modèle d'origine:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
</body>
</html>
Alors que webapp2
utilise des modèles Django qui exécutent des appelables tels que visit.timestamp.ctime
sans parenthèses ( )
, Jinja2 les requiert explicitement. Bien que cela ressemble à un léger ajustement, les modèles Jinja sont plus performants prêts à l'emploi, car il est possible de transmettre des arguments lors des appels.
Dans l'environnement Django, vous devez créer un "tag de modèle" ou écrire un filtre. C'est pourquoi vous devez mettre à jour index.html
en ajoutant une paire de parenthèses à l'appel visit.timestamp.ctime
:
- AVANT :
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
- APRÈS :
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
Il s'agit de la seule modification requise. Vous n'aurez pas à modifier index.html
pour les prochains ateliers de la série.
Déployer l'application
Lorsque vous aurez terminé toutes les modifications décrites dans ce tutoriel, les fichiers du dossier de votre application doivent être identiques (ou presque) à celui situé dans le dossier de dépôt du Module 1. Maintenant, déployez et constatez que votre application Flask Module 1 est identique à la version webapp2
du Module 0.
Utilisez la commande gcloud app deploy
comme nous l'avons fait précédemment lors du déploiement du code du Module 0 d'origine. L'accès à l'application à l'adresse PROJECT_ID.appspot.com
, depuis un navigateur Web ou via une commande curl
ou wget
permet de vérifier qu'elle fonctionne comme prévu.
Si vous rencontrez une erreur de serveur, il s'agit généralement d'une erreur de frappe dans votre code Python. Examinez les journaux de l'application pour rechercher le problème. Comparez également vos fichiers avec ceux du dépôt du Module 1 (lien juste au-dessus).
Facultatif: Effectuer un nettoyage
Que diriez-vous d'un bon nettoyage pour éviter que des frais vous soient facturés tant que vous n'êtes pas prêt à passer à l'atelier de programmation suivant sur la migration ? En tant que développeur existant, vous connaissez probablement déjà les informations de tarification d'App Engine.
Facultatif: Désactiver l'application
Si vous n'êtes pas encore prêt à passer au tutoriel suivant, désactivez votre application pour éviter les frais. Lorsque vous êtes prêt à passer au prochain atelier de programmation, vous pouvez la réactiver. Tant que votre application est désactivée, elle ne génère aucun trafic, donc aucuns frais. Toutefois, si vous dépassez le quota gratuit, votre utilisation de Datastore vous sera facturée, alors supprimez suffisamment d'éléments pour rester dans la limite.
En revanche, si vous ne souhaitez pas poursuivre vos migrations et souhaitez supprimer tous les éléments, vous pouvez arrêter le projet.
Étapes suivantes
Il existe deux modules de migration qui DEMARRENT avec le code du Module 1 terminé, le Module 2 et le Module 7:
- Module 2 (obligatoire si vous utilisez Datastore)
- Migrer depuis App Engine
ndb
vers Cloud NDB - Après être passé à Cloud NDB, de nombreuses autres options deviennent disponibles
- Conteneuriser votre application pour qu'elle s'exécute sur Cloud Run
- Migrer ensuite votre application vers la bibliothèque cliente Cloud Datastore
- Migrer votre application vers Cloud Firestore pour accéder aux fonctionnalités de Firebase
- Migrer depuis App Engine
- Module 7 (obligatoire si vous utilisez les files d'attente de tâches [push])
- Ajouter l'utilisation
taskqueue
d'App Engine (push) - Prépare l'application du Module 1 pour la migration vers Cloud Tasks dans le Module 8
- Ajouter l'utilisation
Problèmes/commentaires concernant le module de migration App Engine en atelier de programmation
Si vous rencontrez des problèmes avec cet atelier de programmation, commencez par faire une recherche avant de les signaler. Liens vers la recherche et la création d'un signalement:
Ressources de migration
Le tableau ci-dessous contient des liens vers les dossiers du dépôt pour les Modules 0 (START) et 1 (FINISH). Vous pouvez également y accéder depuis le dépôt pour toutes les migrations App Engine que vous pouvez cloner ou télécharger sous forme de fichier ZIP.
Atelier de programmation | Python 2 | Python 3 |
Module 0 | (n/a) | |
Module 1 | (n/a) |
Ressources App Engine
Vous trouverez ci-dessous d'autres ressources concernant cette migration en particulier:
- Frameworks micro web Python
- (ANCIEN) Migration de Python 2.5 vers la version 2.7, et
webapp
verswebapp2
- Migrer vers Python 3 et l'environnement d'exécution nouvelle génération GAE
- Général