Esta serie de Codelabs (instructivos prácticos y de autoaprendizaje) tienen como objetivo ayudar a los desarrolladores de Google App Engine (estándar) a modernizar sus apps con una serie de migraciones. El paso más importante es dejar de lado los servicios agrupados del entorno de ejecución porque los entornos de ejecución de última generación son más flexibles y ofrecen a los usuarios una mayor variedad de opciones de servicios. El cambio al entorno de ejecución de generación más reciente te permite la integración en productos de Google Cloud con más facilidad, usar una mayor variedad de servicios compatibles y admitir versiones actuales de lenguaje.
En este instructivo inicial, se muestran los primeros pasos de migración para modernizar el framework web en apps de App Engine: pasar de webapp2
a Flask. En tu aplicación, puedes usar cualquier framework web que maneje el enrutamiento, pero, en este instructivo, usamos Flask, ya que la comunidad lo usa en general.
Obtendrás información para hacer las siguientes acciones
- Usar bibliotecas de terceros (integradas o de otra forma)
- Actualizar archivos de configuración
- Migrar una app simple de
webapp2
a Flask
Qué necesitará
- Un proyecto de Google Cloud Platform con lo siguiente:
- Habilidades básicas de Python
- Conocimiento práctico de comandos básicos de Linux
- Conocimientos básicos sobre el desarrollo y la implementación de aplicaciones de App Engine
Encuesta
¿Cómo usarás este codelab?
El framework webapp
se incluyó cuando App Engine se lanzó en Python 2.5 por primera vez en 2008. Años posteriores se reemplazó por el sucesor webapp2
cuando el entorno de ejecución 2.7 se dejó de usar 2.5 en 2013.
Si bien webapp2
(consulta los documentos) aún existe y se puede usar fuera de App Engine como un framework web que cumple con WSGI, no hace su propio enrutamiento de solicitudes de usuario al código correspondiente en la aplicación. En cambio, se basa en App Engine, los archivos de configuración y el desarrollador para realizar ese enrutamiento de tráfico web a los “controladores” correspondientes. Además, los beneficios principales de webapp2
están, en última instancia, vinculados a los servicios integrados de App Engine, por lo que la daremos de baja, aunque funciona en Python 3 (consulta el problema relacionado).
Este módulo proporciona a los profesionales experiencia práctica para migrar una aplicación webapp2
simple a Flask, un framework compatible con App Engine y muchos más servicios fuera de Google Cloud, lo que hace que las aplicaciones sean mucho más portátiles. Si Flask no es un framework deseado para mover tu aplicación, puedes seleccionar otra siempre que realice su propio enrutamiento. Este codelab muestra a los encargados de la toma de decisiones sobre la tecnología de la información (ITDM) y a los desarrolladores los pasos de migración, por lo que puedes familiarizarte con este proceso, sin importar el framework en el que migras.
A continuación, se muestran los pasos principales para esta migración:
- Configurar/trabajo previo
- Agregar la biblioteca de terceros de Flask
- Actualizar archivos de la aplicación
- Actualizar el archivo de plantilla HTML
Antes de comenzar con la parte principal del instructivo, vamos a configurar nuestro proyecto, obtenemos el código y, luego, te volvemos a familiarizar con el comando de gcloud
e implementaremos la app de modelo de referencia para que comencemos a trabajar con el código.
1. Configura el proyecto
Como desarrollador existente, es probable que el panel de App Engine ya muestre los servicios que tienes en ejecución. A los fines de este instructivo, te recomendamos crear un proyecto nuevo o reutilizar uno existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y que App Engine (app) esté habilitado.
2. Descarga la app de muestra de modelo de referencia
El repositorio de migración de GAE tiene todos los códigos que necesitas. Clona o descarga el archivo ZIP. Para este instructivo, comenzarás con el código en la carpeta del módulo 0 (INICIAR) y, cuando lo hayas completado, tu código debe coincidir con la carpeta del módulo 1 (FINALIZAR). De lo contrario, revisa las diferencias para pasar al siguiente lab.
- INICIAR: Código del módulo 0
- FINALIZAR: Código del módulo 1
- Repositorio completo (para clonar o descargar el archivo ZIP)
La carpeta Módulo 0 debe tener archivos que se vean de la siguiente manera, como se ilustra con el comando ls
de POSIX:
$ ls
app.yaml index.html main.py
3. Vuelve a familiarizarte con los comandos de gcloud
Si aún no tienes el comando de gcloud
en tu máquina, instala el SDK de Google Cloud y asegúrate de que gcloud
esté disponible como parte de tu ruta de ejecución y que te familiarices con los siguientes comandos de gcloud
:
gcloud components update
: actualiza el SDK de Google Cloudgcloud auth login
: accede a tu cuenta con credencialesgcloud config list
: enumera la configuración de un proyecto de GCPgcloud config set project PROJECT_ID
: establece el ID del proyecto de GCPgcloud app deploy
: implementa tu aplicación de App Engine
Si no has realizado desarrollos de App Engine con gcloud
recientemente, debes ejecutar los primeros cuatro comandos (del #1 al #4) para configurarlos antes de continuar con los siguientes pasos. Repasemos rápidamente estos comandos.
En primer lugar, gcloud components update
garantiza que tengas la última versión del SDK de Cloud. Si ejecutas este comando, debería obtener un resultado como el siguiente:
$ 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
A continuación, usa gcloud auth login
a fin de autenticarte para los comandos de gcloud
que emitirás en el futuro:
$ 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
Usa gcloud config list
para ver cuál es la configuración actual de tu proyecto:
$ gcloud config list [core] account = YOUR_EMAIL disable_usage_reporting = False project = PROJECT_ID Your active configuration is: [default]
El comando anterior debe guiarte para crear un proyecto nuevo o seleccionar uno existente. Si la salida de gcloud config list
no coincide con el proyecto seleccionado que planeas usar para este instructivo, ejecuta gcloud config set project PROJECT_ID
a fin de configurar el ID del proyecto. Luego, ejecuta gcloud config list
nuevamente para confirmar el ID del proyecto correcto.
$ gcloud config set project PROJECT_ID Updated property [core/project].
Si prefieres usar Cloud Console, puedes seguir la interfaz de usuario para crear un proyecto nuevo si lo deseas o usar cualquier proyecto existente que ya tengas. En el panel de tu proyecto, deberías ver la tarjeta de información del proyecto que muestra su ID (junto con el nombre y el número del proyecto):
El último comando (#5), gcloud app deploy
, es para implementar tu app en App Engine. Dado que este es solo el comienzo, la ejecución es opcional, pero no desaconsejamos implementar el código del módulo 0 para confirmar que funciona. Luego de la ejecución, selecciona la región geográfica en la que desees que se ejecute la app (por lo general, dónde te encuentras). Sin embargo, no se puede cambiar una vez definido. Luego, mira el resto de la información de la implementación. Cuando se complete, recibirás una notificación sobre la URL en la que se entregará tu app. A continuación, se muestra una versión resumida de lo que puede aparecer:
$ 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 no has usado App Engine por un tiempo, es posible que notes que el comando appcfg.py update
de la implementación original se reemplazó por gcloud app deploy
. Para obtener más información sobre gcloud app deploy
, consulta su página de documentación.
Otro cambio reciente es la URL de las apps implementadas y se modificó de http://PROJECT_ID.appspot.com
a http://PROJECT_ID.REG_ABBR.r.appspot.com
. Con el tiempo, la mayoría de las apps se convertirán al formato nuevo. Obtén más información sobre el formato de URL en la documentación de solicitudes y enrutamiento.
Después de implementar la aplicación, actualiza el navegador (posiblemente varias veces) para ver las visitas más recientes:
Si tu aplicación es nueva, solo verás una o algunas visitas.
El entorno de ejecución de App Engine para Python 2 proporciona un conjunto de bibliotecas de terceros “integradas”, en las que solo debes especificarlos en los archivos app.yaml
que usarás. Aunque esta migración no requiere su uso, estarán en el siguiente instructivo de migración (para el módulo 2).
Las bibliotecas de terceros que no están integradas deben especificarse en un archivo llamado requirements.txt
y deben instalarse de forma local en la carpeta lib
del mismo directorio que el código de la aplicación, en el que se sube todo a App Engine. En la documentación para agrupar bibliotecas de terceros encontrarás más información.
Las bibliotecas copiadas, como Flask, requieren que indiques que App Engine que las busque en la carpeta lib
mediante el archivo de configuración appengine_config.py
. El archivo de configuración appengine_config.py
se ubica en la misma carpeta de la aplicación de nivel superior a requirements.txt
y lib
. En esta parte del instructivo, harás lo que se indica a continuación:
- Crea
requirements.txt
(especifica las bibliotecas copiadas [no integradas] de terceros) - Crea
appengine_config.py
(reconoce las bibliotecas de terceros) - Instala paquetes y dependencias (de terceros)
1. Crea requirements.txt
Crea un archivo requirements.txt
para especificar tus paquetes. En nuestro caso, Flask es la biblioteca de terceros que se necesita. En el momento en el que se redacta este documento, la versión más reciente es 1.1.2, por lo que debes crear requirements.txt
con esta línea:
Flask==1.1.2
Consulta la documentación de requirements.txt
para obtener más información sobre los formatos aceptados.
2. Crea appengine_config.py
En el siguiente paso, harás que App Engine reconozca las bibliotecas externas de terceros. Crea un archivo llamado appengine_config.py
con el siguiente contenido:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Este código hace exactamente lo que especificamos, es decir, apunta a App Engine a la carpeta lib
para las bibliotecas copiadas.
3. Instala paquetes y dependencias
Ahora, ejecuta el comando pip install
para crear la carpeta lib
y, luego, instala Flask y sus dependencias allí:
$ pip install -t lib -r requirements.txt
Ya sea que hayas usado pip
o pip2
, una vez que se completa la instalación del paquete, debes tener una carpeta lib
con contenido similar al siguiente:
$ 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/
Ahora, actualicemos el archivo de la aplicación, main.py
.
1. Importaciones
Las importaciones aparecen primero en todos los archivos de Python. La importación del framework webapp2
está seguida de la biblioteca ndb
de Datastore y, por último, la extensión de App Engine que procesa plantillas con estilo de Django. Debería ver lo siguiente:
- ANTES:
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
Cuando migras a Flask, importas Flask y las imágenes del procesador de plantillas al mismo tiempo. Borra el par de importaciones relacionadas con webapp2
y reemplázalas de la siguiente manera (deja la importación de ndb
como está):
- DESPUÉS:
from flask import Flask, render_template, request
from google.appengine.ext import ndb
2. Inicio
Las apps que usan webapp2
requieren un solo array (lista de Python) que enumera todas las rutas y controladores en cualquier archivo de Python (puede haber otros):
- ANTES:
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
Ten en cuenta que app.yaml
realiza un enrutamiento de un nivel superior y puede llamar a controladores diferentes. La app de muestra es lo suficientemente simple como para que todas las rutas lleguen al controlador main.py
.
Flask no usa tablas de enrutamiento como esta, por lo que debes borrar estas líneas en main.py
. Flask también requiere inicialización, así que agregue la siguiente línea arriba de main.py
justo debajo de las importaciones:
- DESPUÉS:
app = Flask(__name__)
En Flask, debes inicializar el framework y, luego, usar los decoradores para definir las rutas. Además, las rutas se vinculan con funciones, no con clases ni métodos.
Está fuera del alcance incluir un instructivo de Flask en este codelab, por lo que debes revisar el instructivo de Flask y la documentación de Flask para familiarizarte con el framework.
3. Modelo de datos
No hay cambios aquí. Datastore se enfocará en el siguiente codelab.
4. Controladores
La aplicación, sin importar el framework que uses (webapp2
o Flask), realiza las siguientes 3 acciones:
- Controla solicitudes GET de la ruta de acceso raíz (
/
) - Registra una página web “visita” (crea y almacenar el objeto
Visit
) - Muestra las 10 visitas más recientes (con una plantilla predefinida,
index.html
).
El framework webapp2
usa un modelo de ejecución basado en clases en el que se crean los controladores para cada método HTTP compatible. En nuestro caso simple, solo tenemos GET
, por lo que se define un método get()
:
- ANTES:
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}))
Como se mencionó antes, Flask hace su propio enrutamiento. En lugar de una clase de controlador, puedes escribir funciones y decorar con la ruta por la que deberían llamarse. Los usuarios pueden especificar métodos HTTP controlados en la llamada de decorador, es decir, @app.route('/app/', methods=['GET', 'POST'])
. Dado que el valor predeterminado es solo GET
(implícitamente HEAD
), se puede dejar en blanco.
Cuando migres a Flask, reemplaza la clase MainHandler
y su método get()
por la siguiente función de enrutamiento de Flask:
- DESPUÉ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)
Por supuesto, esto no representa a tu app, que será más compleja que esta muestra. Uno de los objetivos principales de estos instructivos es ayudarte a comenzar, compilar parte de esa “memoria muscular” y comprender dónde realizar cambios en el código específico de App Engine. Para confirmar que realizaste este cambio correctamente, compara el suyo con el Módulo 1 main.py
.
5. Archivos auxiliares
No hay cambios en el archivo .gcloudignore
. Su propósito es especificar archivos para no implementar en App Engine y que no son necesarios implementar y ejecutar en la aplicación, incluidos, sin limitaciones a Python auxiliar, control de código fuente, código fuente del repositorio y otros archivos. Nuestro .gcloudignore
se ve así (no se incluyen los comentarios por brevedad):
.gcloudignore
.git
.gitignore
.hgignore
.hg/
*.pyc
*.pyo
__pycache__/
/setup.cfg
README.md
1. Mueve el archivo de plantilla
En la carpeta del repositorio de referencia (módulo 0), el archivo de plantilla index.html
se encuentra en la misma carpeta que los archivos de la aplicación. Como Flask requiere archivos HTML ubicados en una carpeta templates
, debes crear esa carpeta (mkdir templates
) y mover index.html
allí. En un sistema que cumple con POSIX, como Linux o Mac OS X, los comandos serían los siguientes:
mkdir templates
mv index.html templates
2. Actualiza el archivo de plantilla
Una vez que muevas index.html
a templates
, será hora de hacer una edición pequeña, pero obligatoria. Veamos el archivo de plantilla original en su totalidad:
<!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>
Mientras que webapp2
usa plantillas de Django que ejecutan funciones que admiten llamadas como visit.timestamp.ctime
sin paréntesis ( )
, Jinja2 las necesita de forma explícita. Si bien esto parece a un pequeño ajuste, las plantillas de Jinja son más eficaces, listas para usar porque puede pasar argumentos en llamadas.
En Django, tienes que crear una “etiqueta de plantilla” o escribir un filtro. Con esta idea, actualiza index.html
y agrega un par de paréntesis a la llamada visit.timestamp.ctime
:
- ANTES:
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
- DESPUÉS:
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
Este es el único cambio requerido. no se necesitan cambios adicionales para index.html
en todos los Codelabs de migración restantes.
Implemente la aplicación
Cuando hayas completado todos los cambios de este instructivo, los archivos en la carpeta de la aplicación deben ser idénticos (o casi iguales) al archivo en la carpeta del repositorio del módulo 1. Ahora implementa y ve que tu aplicación Flask del módulo 1 se ejecuta de forma idéntica a la versión webapp2
del módulo 0.
Usa el comando gcloud app deploy
como hicimos antes cuando se implementó el código original del módulo 0. Accede a la aplicación en PROJECT_ID.appspot.com
, ya sea desde un navegador web o desde un comando curl
o wget
para confirmar que funciona como se espera.
Si recibes algún tipo de error de servidor, por lo general, significa que se escribirá algún error de ortografía en el código de Python. Consulta los registros de la aplicación para investigar. También compara sus archivos con los del repositorio del módulo 1 (vínculo arriba de la sección).
Opcional: Limpieza
¿Qué te parece limpiar a fin de evitar que se te facture hasta que estés listo para pasar a la siguiente codelab de migración? Como desarrolladores existentes, es probable que ya estés al día en la información sobre precios de App Engine.
Opcional: Inhabilita la app
Si aún no estás listo para continuar con el siguiente instructivo, inhabilita tu app a fin de evitar que se apliquen cargos. Cuando estés listo para pasar al siguiente codelab, puedes volver a habilitarla. Aunque tu app esté inhabilitada, no recibirá tráfico que genere cargos. Sin embargo, si se excede la cuota gratuita, se te cobrará por el uso de Datastore. así que borra lo suficiente para que quede dentro de ese límite.
Por otro lado, si no vas a continuar con las migraciones y quieres borrar todo por completo, puedes cerrar tu proyecto.
Próximos pasos
Hay dos módulos de migración que COMIENZAN con el código del módulo 1, módulo 2 y 7 completado:
- Módulo 2 (obligatorio si usas Datastore)
- Migra de App Engine
ndb
a Cloud NDB - Después de cambiar a Cloud NDB, hay muchas otras opciones disponibles
- Crea contenedores para tu app a fin de que se ejecute en Cloud Run
- Migra aún más tu aplicación a la biblioteca cliente de Cloud Datastore
- Migra tu app a Cloud Firestore para acceder a las funciones de Firebase
- Migra de App Engine
- Módulo 7 (obligatorio si usas las listas de tareas en cola [enviar])
- Agrega el uso de
taskqueue
de App Engine (enviar). - Prepara la app del módulo 1 para la migración a Cloud Tasks en el módulo 8
- Agrega el uso de
Problemas o comentarios de los Codelabs del módulo de migración de App Engine
Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:
Recursos de migración
En la tabla que aparece a continuación, puedes encontrar vínculos a las carpetas del repositorio para el módulo 0 (INICIAR) y el módulo 1 (FINALIZAR). También se puede acceder a ellos desde el repositorio de todas las migraciones de App Engine, que puedes clonar o descargar un archivo ZIP.
Codelab | Python 2 | Python 3 |
Módulo 0 | (n/a) | |
Módulo 1 | (n/a) |
Recursos de App Engine
A continuación, se muestran recursos adicionales con respecto a esta migración específica:
- Microframeworks web de Python
- Migra de Python 2.5 a 2.7 y
webapp
awebapp2
(ANTIGUO) - Migra a Python 3 y GAE de entorno de ejecución de última generación
- General