1. Обзор
Серия обучающих материалов Serverless Migration Station (самостоятельные практические уроки) и сопутствующих видеороликов призвана помочь разработчикам бессерверных приложений Google Cloud модернизировать свои приложения, проведя их через одну или несколько миграций, в первую очередь, через отказ от устаревших сервисов. Это делает ваши приложения более портативными, предоставляет больше возможностей и гибкости, позволяя интегрироваться с более широким спектром облачных продуктов и получать к ним доступ, а также упрощает обновление до более новых версий языков программирования. Хотя изначально серия ориентирована на самых первых пользователей облачных сервисов, в первую очередь разработчиков App Engine (стандартная среда), она достаточно широка, чтобы охватить и другие бессерверные платформы, такие как Cloud Functions и Cloud Run , или другие, если это применимо.
Цель этого практического занятия — показать разработчикам приложений на Python 2 App Engine, как перейти от API/сервиса пользователей App Engine к платформе Cloud Identity Platform (GCIP). Также предусмотрена неявная миграция с App Engine NDB на Cloud NDB для доступа к хранилищу данных (в основном рассматривается в модуле «Миграция 2»), а также обновление до Python 3.
В модуле 20 рассматривается, как добавить использование API пользователей в пример приложения из модуля 1. В этом модуле вы возьмете готовое приложение из модуля 20 и перенесете его использование на платформу Cloud Identity Platform.
Вы узнаете, как
- Замените использование сервиса App Engine Users на платформу Cloud Identity Platform.
- Замените использование App Engine NDB на Cloud NDB (см. также Модуль 2).
- Настройте различные поставщики аутентификации с помощью Firebase Auth.
- Используйте API Cloud Resource Manager для получения информации об IAM проекта.
- Используйте Firebase Admin SDK для получения информации о пользователях.
- Перенесите пример приложения на Python 3.
Что вам понадобится
- Проект на платформе Google Cloud Platform с активным платежным аккаунтом GCP.
- Базовые навыки работы с Python.
- Практические навыки работы с распространенными командами Linux.
- Базовые знания разработки и развертывания приложений на платформе App Engine.
- Рабочий пример приложения, созданного с помощью App Engine (модуль 20).
Опрос
Как вы будете использовать этот учебный материал?
Как бы вы оценили свой опыт работы с Python?
Как бы вы оценили свой опыт использования сервисов Google Cloud?
2. Предыстория
Сервис App Engine Users — это система аутентификации пользователей для приложений App Engine. Он использует Google Sign-In в качестве поставщика идентификации, предоставляет удобные ссылки для входа и выхода из системы в приложениях, а также поддерживает концепцию администраторов и функциональность только для администраторов. Для повышения переносимости приложений Google Cloud рекомендует переходить от устаревших встроенных сервисов App Engine к автономным облачным сервисам , например, от сервиса Users к Cloud Identity Platform и другим.
Платформа Identity основана на Firebase Authentication и добавляет ряд корпоративных функций, включая многофакторную аутентификацию, поддержку единого входа OIDC и SAML, многопользовательский режим, соглашение об уровне обслуживания (SLA) 99,95% и многое другое. Эти различия также отмечены на странице сравнения продуктов Identity Platform и Firebase Authentication . Оба продукта обладают значительно большим функционалом, чем сервис Users.
В этом практическом задании из Модуля 21 демонстрируется переключение аутентификации пользователей приложения со службы Users на функции Identity Platform, что наиболее точно соответствует функциональности, продемонстрированной в Модуле 20. В Модуле 21 также показана миграция с App Engine NDB на Cloud NDB для доступа к Datastore, повторяющая миграцию из Модуля 2 .
Хотя код Модуля 20 «рекламируется» как пример приложения на Python 2, сам исходный код совместим с Python 2 и 3, и это сохраняется даже после миграции на Identity Platform (и Cloud NDB) в Модуле 21. Можно продолжать использовать сервис Users при обновлении до Python 3, поскольку миграция на Identity Platform является необязательной. См. практическое занятие и видео Модуля 17, чтобы узнать, как продолжать использовать встроенные сервисы при обновлении до сред выполнения второго поколения, таких как Python 3.
В этом руководстве описаны следующие шаги:
- Подготовка/Настройка
- Обновить конфигурацию
- Измените код приложения
3. Подготовка/Предварительные работы
В этом разделе объясняется, как:
- Настройте свой облачный проект
- Получите базовый образец приложения
- (Повторное) развертывание и проверка базового приложения.
- Включите новые сервисы/API Google Cloud.
Эти шаги гарантируют, что вы начнете с работающего кода, готового к миграции в автономные облачные сервисы.
1. Настройка проекта
Если вы выполнили практическое задание по модулю 20, используйте тот же проект (и код). В качестве альтернативы создайте совершенно новый проект или используйте другой существующий проект. Убедитесь, что у проекта есть активный платежный аккаунт и включенное приложение App Engine. Найдите идентификатор своего проекта и держите его под рукой во время выполнения этого практического задания, используя его всякий раз, когда вы встречаете переменную PROJ_ID .
2. Получите базовый образец приложения.
Одно из необходимых условий — наличие работающего приложения App Engine модуля 20, поэтому либо пройдите его практическое занятие (рекомендуется; ссылка выше), либо скопируйте код модуля 20 из репозитория. Независимо от того, используете ли вы свой или наш код, мы начнем с этого («НАЧАЛО»). Это практическое занятие проведет вас через процесс миграции и завершится кодом, похожим на тот, что находится в папке репозитория модуля 21 («ЗАВЕРШЕНИЕ»).
- НАЧАЛО: Папка модуля 20 (Python 2)
- ЗАВЕРШЕНИЕ: Папки модуля 21 ( Python 2 или Python 3 )
- Весь репозиторий (для клонирования или загрузки ZIP-файла )
Скопируйте папку репозитория модуля 20. Она должна выглядеть примерно так, как показано ниже, и, возможно, будет содержать папку lib , если вы выполняли практическое задание по модулю 20:
$ ls README.md appengine_config.py templates app.yaml main.py requirements.txt
3. (Повторное) развертывание и проверка базового приложения.
Для развертывания приложения «Модуль 20» выполните следующие действия:
- Удалите папку
libесли она существует, и выполните командуpip install -t lib -r requirements.txtчтобы заполнить её заново. Возможно, вам потребуется использоватьpip2если у вас установлены Python 2 и 3. - Убедитесь, что вы установили и инициализировали инструмент командной строки
gcloudи ознакомились с его использованием . - Если вы не хотите вводить свой
PROJ_IDпри каждой командеgcloud, сначала настройте проект Cloud с помощьюgcloud config set projectPROJ_ID. - Разверните демонстрационное приложение с помощью
gcloud app deploy - Убедитесь, что приложение работает должным образом и без ошибок. Если вы выполнили практическое задание модуля 20, приложение отображает информацию для входа пользователя (адрес электронной почты пользователя, возможный «значок администратора» и кнопку входа/выхода) вверху, а также информацию о последних посещениях (иллюстрация ниже).

При входе в систему под учетной записью обычного пользователя отображается его адрес электронной почты, а кнопка «Вход» заменяется на кнопку «Выход».

При входе в систему под учетной записью администратора отображается адрес электронной почты пользователя, а рядом с ним — "(admin)":

4. Активируйте новые API/сервисы Google Cloud.
Введение
Приложение Module 20 использует API App Engine NDB и Users — встроенные сервисы, не требующие дополнительной настройки, в отличие от автономных облачных сервисов, которые требуют дополнительной настройки. Обновленное приложение будет использовать как Cloud Identity Platform, так и Cloud Datastore (через клиентскую библиотеку Cloud NDB ). Кроме того, для определения административных пользователей App Engine нам также необходим API Cloud Resource Manager .
Расходы
- В App Engine и Cloud Datastore действуют квоты на тарифный план "Всегда бесплатно" , и пока вы не превышаете эти лимиты, за выполнение этого руководства с вас не должно взиматься плата. Более подробную информацию можно найти на страницах с ценами App Engine и Cloud Datastore .
- Использование платформы Cloud Identity Platform оплачивается в зависимости от количества ежемесячно активных пользователей (MAU) или проверок аутентификации; для каждой модели использования доступен вариант «бесплатного» использования. Подробнее см. на странице с ценами . Кроме того, хотя App Engine и Cloud Datastore требуют оплаты, использование GCIP само по себе не требует включения оплаты, если вы не превышаете ежедневные квоты без использования инструментов , поэтому учитывайте это для облачных проектов, которые не включают в себя облачные API/сервисы, требующие оплаты.
- Согласно информации на странице с ценами, использование API Cloud Resource Manager в большинстве случаев бесплатно.
Пользователи могут включать API Cloud через консоль Cloud или из командной строки (с помощью команды gcloud , входящей в состав Cloud SDK ), в зависимости от своих предпочтений. Давайте начнем с API Cloud Datastore и Cloud Resource Manager.
Из облачной консоли
Перейдите на страницу библиотеки API Manager (для соответствующего проекта) в консоли Cloud Console и найдите API с помощью строки поиска. 
Включите следующие API:
Найдите и нажмите кнопку «Включить» для каждого API отдельно — возможно, вам потребуется ввести платежную информацию. Например, вот страница для API Resource Manager:

После активации кнопка меняет цвет на «Управление» (обычно через несколько секунд):

Включите Cloud Datastore аналогичным образом:

Из командной строки
Хотя включение API из консоли визуально информативно, некоторые предпочитают командную строку. Дополнительным преимуществом является возможность включения любого количества API одновременно. Выполните эту команду, чтобы включить API Cloud Datastore и Cloud Resource Manager, и дождитесь завершения операции, как показано здесь:
$ gcloud services enable cloudresourcemanager.googleapis.com datastore.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
Возможно, вас попросят ввести платежную информацию.
URL-адреса каждого API, используемого в приведенной выше команде, называются именами служб API, и их можно найти внизу страницы библиотеки для каждого API. Если вы хотите включить другие облачные API для своих приложений, вы можете найти соответствующие имена служб на страницах соответствующих API. Эта команда выводит список всех имен служб для API, которые вы можете включить:
gcloud services list --available --filter="name:googleapis.com" .
После выполнения описанных выше шагов наш пример сможет получить доступ к этим API как в консоли Cloud, так и в командной строке. Следующие шаги — включение платформы Cloud Identity Platform и внесение необходимых изменений в код.
Включение и настройка платформы облачной идентификации (только в облачной консоли).
Платформа Cloud Identity Platform — это сервис из Marketplace , поскольку она подключается к ресурсам, находящимся за пределами Google Cloud, или зависит от них, например, от Firebase Authentication . В настоящее время включить сервисы Marketplace можно только через консоль Cloud. Выполните следующие шаги:
- Перейдите на страницу Cloud Identity Platform в Cloud Marketplace и нажмите кнопку «Включить» . При появлении запроса выполните обновление с Firebase Authentication — это разблокирует дополнительные функции, например, описанные ранее в разделе «Введение» . Вот страница Marketplace, на которой выделена кнопка «Включить» :

- После включения Identity Platform вы можете автоматически перейти на страницу поставщиков идентификационных данных . В противном случае воспользуйтесь этой удобной ссылкой , чтобы попасть туда.

- Включите поставщика аутентификации Google. Если поставщики еще не настроены, нажмите «Добавить поставщика» и выберите Google . После возвращения на этот экран запись Google должна быть включена. Google — единственный поставщик аутентификации, который мы используем в этом руководстве, чтобы воспроизвести службу App Engine Users в качестве облегченной службы входа через Google. В своих приложениях вы можете включить дополнительные поставщики аутентификации.
- После выбора и настройки Google и других необходимых поставщиков аутентификации нажмите «Подробности настройки приложения» , и в появившемся диалоговом окне скопируйте
apiKeyиauthDomainиз объектаconfigна вкладке «Веб», сохранив их в надежном месте. Почему бы не скопировать все? Фрагмент кода в этом диалоговом окне жестко закодирован и устарел, поэтому сохраните только самые важные данные и используйте их в коде при одновременном использовании Firebase Auth. После того, как вы скопировали значения и сохранили их в надежном месте, нажмите кнопку «Закрыть» , завершив все необходимые настройки.
4. Обновите конфигурацию
Обновления конфигурации включают в себя как изменение различных конфигурационных файлов, так и создание аналога App Engine, но в рамках экосистемы Cloud Identity Platform.
appengine_config.py
- При переходе на Python 3 удалите
appengine_config.py - Если вы планируете перейти на Identity Platform, но остаться на Python 2, не удаляйте этот файл. Вместо этого мы обновим его позже в процессе переноса кода на Python 2.
requirements.txt
В файле requirements.txt модуля 20 указан только Flask . Для модуля 21 добавьте следующие пакеты:
Содержимое файла requirements.txt теперь должно выглядеть следующим образом:
flask
google-auth
google-cloud-ndb
google-cloud-resource-manager
firebase-admin
app.yaml
- Переход на Python 3 подразумевает упрощение файла
app.yaml. Удалите все, кроме директивы runtime, и установите для нее поддерживаемую в настоящее время версию Python 3. В примере в настоящее время используется версия 3.10. - Если вы остаетесь с Python 2, пока ничего здесь не предпринимайте.
ДО:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
В примере приложения из модуля 20 отсутствуют статические обработчики файлов. Если в ваших приложениях они есть, оставьте их без изменений. При желании вы можете удалить все обработчики скриптов или оставить их только для справки, изменив их дескрипторы на auto , как описано в руководстве по миграции app.yaml . С этими изменениями обновленный app.yaml для Python 3 упрощается до:
ПОСЛЕ:
runtime: python310
Другие обновления конфигурации
Независимо от того, остаетесь ли вы на Python 2 или переходите на Python 3, если у вас есть папка lib , удалите её.
5. Измените код приложения.
В этом разделе представлены обновления основного файла приложения, main.py , заменяющие использование службы App Engine Users на Cloud Identity Platform. После обновления основного приложения вам также потребуется обновить веб-шаблон, templates/index.html .
Обновление импорта и инициализации
Для обновления импортированных данных и инициализации ресурсов приложения выполните следующие действия:
- При импорте замените App Engine NDB на Cloud NDB.
- Наряду с Cloud NDB, импортируйте также Cloud Resource Manager.
- Платформа Identity Platform основана на Firebase Auth, поэтому импортируйте Firebase Admin SDK.
- Для работы с облачными API требуется использовать API-клиент, поэтому инициализируйте его для Cloud NDB сразу после инициализации Flask.
Хотя пакет Cloud Resource Manager импортируется здесь, мы будем использовать его позже при инициализации приложения. Ниже приведены импорт и инициализация из модуля 20, а затем показано, как должны выглядеть разделы после внесения вышеуказанных изменений:
ДО:
from flask import Flask, render_template, request
from google.appengine.api import users
from google.appengine.ext import ndb
app = Flask(__name__)
ПОСЛЕ:
from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app
# initialize Flask and Cloud NDB API client
app = Flask(__name__)
ds_client = ndb.Client()
Поддержка администраторов App Engine
Для поддержки распознавания администраторов в приложение необходимо добавить два компонента:
-
_get_gae_admins()— собирает набор администраторов; вызывается один раз и сохраняется. -
is_admin()— проверяет, является ли вошедший в систему пользователь администратором; вызывается при каждом входе пользователя в систему.
Вспомогательная функция _get_gae_admins() вызывает API Resource Manager для получения текущей политики разрешений Cloud IAM . Политика разрешений определяет и обеспечивает соблюдение того, какие роли предоставляются каким субъектам (пользователям, учетным записям служб и т. д.). Настройка включает в себя:
- Получение идентификатора облачного проекта (
PROJ_ID) - Создание клиента API Resource Manager (
rm_client) - Создание набора ролей администратора App Engine (только для чтения) (
_TARGETS)
Для работы Resource Manager требуется идентификатор облачного проекта, поэтому импортируйте google.auth.default() и вызовите эту функцию, чтобы получить идентификатор проекта. Этот вызов содержит параметр, который выглядит как URL-адрес, но представляет собой область разрешений OAuth2 . При запуске приложений в облаке, например, на виртуальной машине Compute Engine или в приложении App Engine, предоставляется учетная запись службы по умолчанию с широкими привилегиями. В соответствии с принципом минимальных привилегий мы рекомендуем создавать собственные управляемые пользователями учетные записи служб .
Для вызовов API лучше всего дополнительно ограничить область действия ваших приложений до минимального уровня, необходимого для корректной работы. Вызов API Resource Manager, который мы будем выполнять, — это get_iam_policy() , для работы которого требуется одна из следующих областей действия:
-
https://www.googleapis.com/auth/cloud-platform -
https://www.googleapis.com/auth/cloud-platform.read-only -
https://www.googleapis.com/auth/cloudplatformprojects -
https://www.googleapis.com/auth/cloudplatformprojects.readonly
Для тестового приложения требуется только доступ на чтение к политике разрешений. Оно не изменяет политику и не нуждается в доступе ко всему проекту. Это означает, что приложению не требуются первые три разрешения. Требуется только последнее, и именно его мы реализуем для тестового приложения.
Основная часть функции создает пустой набор пользователей-администраторов ( admins ), получает значение allow_policy с помощью get_iam_policy() и перебирает все его привязки, ища конкретно роли администратора App Engine:
-
roles/viewer -
roles/editor -
roles/owner -
roles/appengine.appAdmin
Для каждой найденной целевой роли система подбирает пользователей, принадлежащих к этой роли, и добавляет их к общему набору администраторов. В конце возвращается список всех найденных администраторов, которые кэшируются в виде константы ( _ADMINS ) на протяжении всего времени работы этого экземпляра App Engine. Мы увидим этот вызов чуть позже.
Добавьте в main.py следующее определение функции _get_gae_admins() сразу после создания экземпляра клиента Cloud NDB API ( ds_client ):
def _get_gae_admins():
'return set of App Engine admins'
# setup constants for calling Cloud Resource Manager API
_, PROJ_ID = default( # Application Default Credentials and project ID
['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()
_TARGETS = frozenset(( # App Engine admin roles
'roles/viewer',
'roles/editor',
'roles/owner',
'roles/appengine.appAdmin',
))
# collate users who are members of at least one GAE admin role (_TARGETS)
admins = set() # set of all App Engine admins
allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
for b in allow_policy.bindings: # bindings in IAM allow-policy
if b.role in _TARGETS: # only look at GAE admin roles
admins.update(user.split(':', 1).pop() for user in b.members)
return admins
Когда пользователи входят в приложение, происходит следующее:
- После входа пользователя в Firebase выполняется быстрая проверка на основе веб-шаблона.
- Когда состояние аутентификации изменяется в шаблоне, выполняется вызов функции
fetch()в стиле Ajax к/is_admin, обработчиком которой является следующая функция,is_admin(). - Идентификационный токен Firebase передается в теле POST-запроса функции
is_admin(), которая извлекает его из заголовков и вызывает SDK администратора Firebase для проверки. Если это действительный пользователь, извлекается его адрес электронной почты и проверяется, является ли он администратором. - Затем логический результат возвращается в шаблон как успешный код 200.
Добавьте is_admin() в main.py сразу после _get_gae_admins() :
@app.route('/is_admin', methods=['POST'])
def is_admin():
'check if user (via their Firebase ID token) is GAE admin (POST) handler'
id_token = request.headers.get('Authorization')
email = auth.verify_id_token(id_token).get('email')
return {'admin': email in _ADMINS}, 200
Весь код обеих функций необходим для воспроизведения функциональности, доступной в службе Users, в частности, её функции is_current_user_admin() . В модуле 20 эта функция выполняла всю основную работу, в отличие от модуля 21, где мы реализовали альтернативное решение. Хорошая новость заключается в том, что приложение больше не зависит от службы, работающей только в App Engine, а это значит, что вы можете перенести свои приложения в Cloud Run или другие службы. Кроме того, вы можете изменить определение «администратор» для своих приложений, просто переключившись на нужные роли в _TARGETS тогда как в службе Users роли администратора в App Engine заданы жестко.
Инициализация Firebase Auth и кэширование административных пользователей App Engine.
Мы могли бы инициализировать Firebase Auth в самом начале, примерно в том же месте, где инициализируется приложение Flask и создается клиент Cloud NDB API, но в этом не было необходимости, пока не был определен весь административный код, что мы и делаем сейчас. Аналогично, теперь, когда определена функция _get_gae_admins() , вызовите ее для кэширования списка администраторов.
Добавьте эти строки сразу под телом функции is_admin() :
# initialize Firebase and fetch set of App Engine admins
initialize_app()
_ADMINS = _get_gae_admins()
Обновления модели данных посещений
Модель данных Visit остается неизменной. Для доступа к Datastore требуется явное использование менеджера контекста клиента Cloud NDB API, ds_client.context() . В коде это означает, что вы должны обернуть вызовы Datastore в функции store_visit() и fetch_visits() внутри Python with . Это обновление идентично модулю 2. Внесите следующие изменения:
ДО:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
ПОСЛЕ:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Перенесите логику авторизации пользователей в веб-шаблон.
Сервис App Engine Users работает на стороне сервера, в то время как Firebase Auth и Cloud Identity Platform преимущественно работают на стороне клиента. В результате большая часть кода управления пользователями в приложении Модуля 20 переносится в веб-шаблон Модуля 21.
В main.py веб-контекст передает шаблону пять важных элементов данных; первые четыре связаны с управлением пользователями и различаются в зависимости от того, авторизован пользователь или нет:
-
who— адрес электронной почты пользователя, если он авторизован, или пользователя в противном случае. -
admin— значок (admin) , если вошедший в систему пользователь является администратором. - —
signкнопку «Вход» или «Выход» . -
link— ссылки для входа или выхода при нажатии кнопки -
visits— самые последние посещения
ДО:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
# put together users context for web template
user = users.get_current_user()
context = { # logged in
'who': user.nickname(),
'admin': '(admin)' if users.is_current_user_admin() else '',
'sign': 'Logout',
'link': '/_ah/logout?continue=%s://%s/' % (
request.environ['wsgi.url_scheme'],
request.environ['HTTP_HOST'],
), # alternative to users.create_logout_url()
} if user else { # not logged in
'who': 'user',
'admin': '',
'sign': 'Login',
'link': users.create_login_url('/'),
}
# add visits to context and render template
context['visits'] = visits # display whether logged in or not
return render_template('index.html', **context)
Все функции управления пользователями переносятся в веб-шаблон, поэтому у нас остается только отслеживание посещений, и основной обработчик возвращается к тому, что было еще в приложении Модуля 1:
ПОСЛЕ:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
return render_template('index.html', visits=visits)
Обновить веб-шаблон
Как выглядят все обновления из предыдущего раздела в шаблоне? В основном, это перенос управления пользователями из приложения в Firebase Auth, работающий в шаблоне, и частичный перенос всего этого кода на JavaScript. Мы заметили значительное сокращение размера main.py , поэтому ожидайте аналогичного роста в templates/index.html .
ДО:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
</head>
<body>
<p>
Welcome, {{ who }} <code>{{ admin }}</code>
<button id="logbtn">{{ sign }}</button>
</p><hr>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
<script>
document.getElementById("logbtn").onclick = () => {
window.location.href = '{{ link }}';
};
</script>
</body>
</html>
Замените весь веб-шаблон содержимым, приведенным ниже:
ПОСЛЕ:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<script type="module">
// import Firebase module attributes
import {
initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
GoogleAuthProvider,
getAuth,
onAuthStateChanged,
signInWithPopup,
signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";
// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
};
// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});
// define login and logout button functions
function login() {
signInWithPopup(auth, provider);
};
function logout() {
signOut(auth);
};
// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
if (user && user != null) {
var email = user.email;
who.innerHTML = email;
logbtn.onclick = logout;
logbtn.innerHTML = "Logout";
var idToken = await user.getIdToken();
var rsp = await fetch("/is_admin", {
method: "POST",
headers: {Authorization: idToken}
});
var data = await rsp.json();
if (data.admin) {
admin.style.display = "inline";
}
} else {
who.innerHTML = "user";
admin.style.display = "none";
logbtn.onclick = login;
logbtn.innerHTML = "Login";
}
});
</script>
</head>
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
<script>
var who = document.getElementById("who");
var admin = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>
В этом HTML-коде много компонентов, поэтому давайте рассмотрим их по одному.
Импорт Firebase
Находясь в заголовке HTML-документа, после заголовка страницы, импортируйте необходимые компоненты Firebase. Компоненты Firebase теперь разбиты на несколько модулей для повышения эффективности. Код для инициализации Firebase импортируется из основного модуля приложения Firebase, а функции, управляющие аутентификацией Firebase, Google в качестве поставщика аутентификации, входом и выходом из системы, а также функцией обратного вызова при изменении состояния аутентификации, импортируются из модуля Firebase Auth:
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<script type="module">
// import Firebase module attributes
import {
initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
GoogleAuthProvider,
getAuth,
onAuthStateChanged,
signInWithPopup,
signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";
Конфигурация Firebase
Ранее, в разделе настройки платформы идентификации, вы сохранили apiKey и authDomain из диалогового окна « Подробности настройки приложения» . Добавьте эти значения в переменную firebaseConfig в следующем разделе. Ссылка на более подробные инструкции приведена в комментариях:
// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
};
Инициализация Firebase
В следующем разделе выполняется инициализация Firebase с использованием этих конфигурационных данных.
// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});
Это позволяет использовать Google в качестве поставщика аутентификации и предоставляет закомментированную опцию для отображения выбора учетной записи, даже если в вашей браузерной сессии зарегистрирована только одна учетная запись Google. Другими словами, при наличии нескольких учетных записей вам будет показан этот «выбор учетной записи», как и ожидалось:
Однако, если в сессии только один пользователь, процесс входа в систему завершается автоматически без какого-либо взаимодействия с пользователем. (Всплывающее окно появляется, а затем исчезает.) Вы можете принудительно отобразить диалоговое окно выбора учетной записи для одного пользователя (вместо немедленного входа в приложение), раскомментировав строку с пользовательским параметром. Если эта функция включена, диалоговое окно выбора учетной записи будет отображаться даже при входе одного пользователя: 
Функции входа и выхода из системы
Следующие строки кода содержат функции для обработки нажатий кнопок входа или выхода из системы:
// define login and logout button functions
function login() {
signInWithPopup(auth, provider);
};
function logout() {
signOut(auth);
};
Действия входа и выхода из системы
Последний важный раздел в этом блоке <script> — это функция, которая вызывается при каждом изменении авторизации (вход или выход из системы).
// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
if (user && user != null) {
var email = user.email;
who.innerHTML = email;
logbtn.onclick = logout;
logbtn.innerHTML = "Logout";
var idToken = await user.getIdToken();
var rsp = await fetch("/is_admin", {
method: "POST",
headers: {Authorization: idToken}
});
var data = await rsp.json();
if (data.admin) {
admin.style.display = "inline";
}
} else {
who.innerHTML = "user";
admin.style.display = "none";
logbtn.onclick = login;
logbtn.innerHTML = "Login";
}
});
</script>
</head>
Здесь происходит переход от кода в модуле 20, определяющего, следует ли отправлять контекст шаблона «пользователь авторизован» или «пользователь не авторизован». Условное выражение вверху возвращает true , если пользователь успешно авторизован, что запускает следующие действия:
- Адрес электронной почты пользователя настроен для отображения.
- Кнопка «Вход» меняется на «Выход» .
- Для определения того, следует ли отображать значок администратора
(admin)используется Ajax-запрос к методу/is_admin.
Когда пользователь выходит из системы, выполняется блок else для сброса всех пользовательских данных:
- Имя пользователя установлено на user
- Административный значок удален
- Кнопка «Выход» снова стала кнопкой «Вход».
Переменные шаблона
После заголовка начинается основная часть текста, содержащая переменные шаблона, которые заменяются HTML-элементами, изменяющимися по мере необходимости:
- Отображаемое имя пользователя
-
(admin)значок администратора (если применимо) - Кнопка входа или выхода
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>
Последние посещения и переменные HTML-элементов
Код последних посещений не меняется, а последний блок <script> устанавливает переменные для HTML-элементов, которые изменяются при входе и выходе из системы, перечисленных выше:
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
<script>
var who = document.getElementById("who");
var admin = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>
На этом завершаются изменения, необходимые в приложении и веб-шаблоне для перехода с App Engine NDB и API пользователей на Cloud NDB и Identity Platform, а также для обновления до Python 3. Поздравляем с созданием нового примера приложения для Модуля 21! Наша версия доступна для ознакомления в папке репозитория Модуля 21b .
Следующая часть практического занятия является необязательной (*) и предназначена только для пользователей, чьи приложения должны оставаться на Python 2. В ней вы найдете пошаговое руководство по созданию работающего приложения Python 2 Module 21.
6. *Бэкпорт Python 2
Этот необязательный раздел предназначен для разработчиков, выполняющих миграцию Identity Platform, но которым необходимо продолжать работу в среде выполнения Python 2. Если это вас не касается, пропустите этот раздел.
Для создания рабочей версии приложения «Модуль 21» на Python 2 вам потребуется следующее:
- Требования к среде выполнения : Конфигурационные файлы, поддерживающие Python 2, и необходимые изменения в основном приложении во избежание несовместимости с Python 3.
- Незначительное изменение в библиотеке: Python 2 был объявлен устаревшим до того, как в клиентскую библиотеку Resource Manager были добавлены некоторые необходимые функции. В результате вам потребуется альтернативный способ доступа к отсутствующей функциональности.
Давайте перейдем к этим шагам, начиная с настройки.
Восстановите файл appengine_config.py
Ранее в этом руководстве вам было предложено удалить appengine_config.py поскольку он не используется средой выполнения Python 3 App Engine. Для Python 2 его необходимо не только сохранить, но и обновить файл appengine_config.py модуля 20, чтобы он поддерживал использование встроенных сторонних библиотек , а именно grpcio и setuptools . Эти пакеты необходимы, если ваше приложение App Engine использует клиентские библиотеки Cloud, такие как Cloud NDB и Cloud Resource Manager.
Вы добавите эти пакеты в app.yaml чуть позже, но для того, чтобы ваше приложение могло получить к ним доступ, необходимо вызвать функцию pkg_resources.working_set.add_entry() из setuptools . Это позволит скопированным (самостоятельно включенным или включенным в пакет) сторонним библиотекам, установленным в папке lib , взаимодействовать со встроенными библиотеками.
Для вступления изменений в силу внесите следующие изменения в файл appengine_config.py :
ДО:
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
Одного этого кода недостаточно для поддержки использования setuptools и grpcio . Необходимо добавить ещё несколько строк, поэтому обновите appengine_config.py так, чтобы он выглядел следующим образом:
ПОСЛЕ:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
Более подробная информация об изменениях, необходимых для поддержки клиентских библиотек облачных сервисов, содержится в документации по миграции встроенных сервисов .
app.yaml
Аналогично файлу appengine_config.py , файл app.yaml необходимо привести в соответствие с требованиями Python 2. Начнём с исходного файла app.yaml из модуля 20:
ДО:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Помимо setuptools и grpcio как упоминалось ранее, существует зависимость (не связанная напрямую с миграцией на платформу идентификации), требующая использования клиентской библиотеки Cloud Storage , для которой , в свою очередь, необходим еще один встроенный сторонний пакет — ssl . Добавьте все три пакета в новый раздел libraries , выбрав «последние» доступные версии этих пакетов, в app.yaml :
ПОСЛЕ:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
requirements.txt
Для модуля 21 мы добавили Google Auth , Cloud NDB , Cloud Resource Manager и Firebase Admin SDK в файл requirements.txt для Python 3. Ситуация с Python 2 сложнее:
- API Resource Manager предоставляет функциональность политик разрешений, необходимую для демонстрационного приложения. К сожалению, эта поддержка еще не была доступна в финальной версии клиентской библиотеки Cloud Resource Manager для Python 2. (Она доступна только в версии для Python 3.)
- В результате требуется альтернативный способ доступа к этой функции через API. Решение заключается в использовании низкоуровневой клиентской библиотеки Google API для взаимодействия с API. Чтобы перейти на эту клиентскую библиотеку, замените
google-cloud-resource-managerна низкоуровневый пакетgoogle-api-python-client. - Поскольку поддержка Python 2 прекращена , граф зависимостей, поддерживающий модуль 21, требует привязки определенных пакетов к конкретным версиям. Некоторые пакеты необходимо указывать, даже если они не указаны в
app.yamlPython 3.
ДО:
flask
Начиная с файла requirements.txt модуля 20, обновите его следующим образом, чтобы приложение модуля 21 работало:
ПОСЛЕ:
grpcio==1.0.0
protobuf<3.18.0
six>=1.13.0
flask
google-gax<0.13.0
google-api-core==1.31.1
google-api-python-client<=1.11.0
google-auth<2.0dev
google-cloud-datastore==1.15.3
google-cloud-firestore==1.9.0
google-cloud-ndb
google-cloud-pubsub==1.7.0
firebase-admin
Номера пакетов и версий будут обновляться в репозитории по мере изменения зависимостей, но на момент написания этого текста для работающего приложения достаточно данного файла app.yaml .
Другие обновления конфигурации
Если вы не удалили папку lib из предыдущих заданий этого практического занятия, сделайте это сейчас. Используя обновленный файл requirements.txt , выполните следующую команду, чтобы установить необходимые зависимости в lib :
pip install -t lib -r requirements.txt # or pip2
Если на вашей системе разработки установлены Python 2 и 3, вам может потребоваться использовать pip2 вместо pip .
Измените код приложения
К счастью, большинство необходимых изменений находятся в конфигурационных файлах. Единственное изменение, необходимое в коде приложения, — это небольшое обновление для использования клиентской библиотеки Google API нижнего уровня вместо клиентской библиотеки Resource Manager для доступа к API. Обновления веб-шаблона templates/index.html не требуются.
Обновление импорта и инициализации
Замените клиентскую библиотеку Resource Manager ( google.cloud.resourcemanager ) на клиентскую библиотеку Google API ( googleapiclient.discovery ), как показано ниже:
ДО:
from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app
ПОСЛЕ:
from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb
from googleapiclient import discovery
from firebase_admin import auth, initialize_app
Поддержка администраторов App Engine
Для поддержки использования клиентской библиотеки нижнего уровня необходимо внести несколько изменений в функцию _get_gae_admins() . Давайте сначала обсудим, что именно меняется, а затем предоставим вам весь код для обновления.
В коде Python 2 требуется использовать как учетные данные, так и идентификатор проекта, возвращаемый функцией google.auth.default() . Учетные данные не используются в Python 3, поэтому они были присвоены универсальной фиктивной переменной с подчеркиванием ( _ ). Поскольку это необходимо для версии Python 2, замените подчеркивание на CREDS . Кроме того, вместо создания клиента API Resource Manager вы создадите конечную точку службы API, аналогичную по концепции клиенту API, поэтому мы сохраняем то же имя переменной ( rm_client ). Одно из отличий заключается в том, что для создания экземпляра конечной точки службы требуются учетные данные ( CREDS ).
Эти изменения отражены в приведенном ниже коде:
ДО:
_, PROJ_ID = default( # Application Default Credentials and project ID
['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()
ПОСЛЕ:
CREDS, PROJ_ID = default( # Application Default Credentials and project ID
['https://www.googleapis.com/auth/cloud-platform'])
rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)
Другое отличие заключается в том, что клиентская библиотека Resource Manager возвращает объекты allow-policy, использующие точечную нотацию атрибутов, в то время как клиентская библиотека нижнего уровня возвращает словари Python, где используются квадратные скобки ( [ ] ), например, для клиентской библиотеки Resource Manager используется binding.role , а для библиотеки нижнего уровня binding['role'] . Первая также использует имена, разделенные подчеркиванием, в то время как библиотека нижнего уровня предпочитает имена в стиле CamelCase, а также немного другой способ передачи параметров API.
Эти различия в использовании показаны ниже:
ДО:
allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
for b in allow_policy.bindings: # bindings in IAM allow-policy
if b.role in _TARGETS: # only look at GAE admin roles
admins.update(user.split(':', 1).pop() for user in b.members)
ПОСЛЕ:
allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
for b in allow_policy['bindings']: # bindings in IAM allow-policy
if b['role'] in _TARGETS: # only look at GAE admin roles
admins.update(user.split(':', 1).pop() for user in b['members'])
Учитывая все эти изменения, замените функцию _get_gae_admins() в Python 3 на эквивалентную версию в Python 2:
def _get_gae_admins():
'return set of App Engine admins'
# setup constants for calling Cloud Resource Manager API
CREDS, PROJ_ID = default( # Application Default Credentials and project ID
['https://www.googleapis.com/auth/cloud-platform'])
rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)
_TARGETS = frozenset(( # App Engine admin roles
'roles/viewer',
'roles/editor',
'roles/owner',
'roles/appengine.appAdmin',
))
# collate users who are members of at least one GAE admin role (_TARGETS)
admins = set() # set of all App Engine admins
allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
for b in allow_policy['bindings']: # bindings in IAM allow-policy
if b['role'] in _TARGETS: # only look at GAE admin roles
admins.update(user.split(':', 1).pop() for user in b['members'])
return admins
Функция is_admin() не требует никаких обновлений, поскольку она зависит от _get_gae_admins() , которая уже была обновлена.
На этом завершаются изменения, необходимые для переноса приложения из модуля 21 Python 3 на Python 2. Поздравляем с созданием обновленного примера приложения из модуля 21! Весь код вы найдете в папке репозитория модуля 21a .
7. Подведение итогов/Завершение
Последние шаги в практическом задании заключаются в том, чтобы убедиться, что у субъектов (пользователей или учетных записей служб), запускающих это приложение, есть необходимые разрешения, а затем развернуть приложение, чтобы подтвердить его корректную работу и отражение изменений в результатах.
Умение читать политику разрешений IAM.
Ранее мы познакомили вас с четырьмя ролями, необходимыми для того, чтобы считаться администратором App Engine, но теперь нужно ознакомиться и с пятой:
-
roles/viewer -
roles/editor -
roles/owner -
roles/appengine.appAdmin -
roles/resourcemanager.projectIamAdmin(для субъектов, имеющих доступ к политике разрешений IAM)
Роль roles/resourcemanager.projectIamAdmin позволяет субъектам определять, является ли конечный пользователь членом какой-либо из административных ролей App Engine. Без членства в roles/resourcemanager.projectIamAdmin вызовы API Cloud Resource Manager для получения политики разрешений завершатся неудачей.
You do not need to take any explicit action here as your app will run under App Engine's default service account which is automatically granted membership in this role. Even if you use the default service account during the development phase, we strongly recommend creating and using a user-managed service account with the minimal permissions required for your app to function properly. To grant membership to such a service account, run the following command:
$ gcloud projects add-iam-policy-binding PROJ_ID --member="serviceAccount:USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com" --role=roles/resourcemanager.projectIamAdmin
PROJ_ID is the Cloud project ID and USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com is the user-managed service account you create for your app. This command outputs the updated IAM policy for your project where you can confirm the service account has membership in roles/resourcemanager.projectIamAdmin . For more information, see the reference documentation . To repeat, you don't need to issue that command in this codelab, but save this as a reference for modernizing your own apps.
Deploy and verify application
Upload your app to the cloud with the standard gcloud app deploy command. Once deployed, you should see functionality almost identical to the Module 20 app except that you've successfully replaced the App Engine Users service with the Cloud Identity Platform (and Firebase Auth) for user management:

One difference you'll notice compared to Module 20 is that clicking on the Login results in a popup instead of a redirect, captured in some of the screenshots below. Like Module 20 however, the behavior differs slightly depending on how many Google accounts have been registered with the browser.
If there are no users registered with the browser or a single user who hasn't signed in yet, a generic Google Sign-in popup comes up:

If a single user is registered with your browser but signs-in elsewhere, no dialog appears (or it pops up and closes immediately), and the app goes into a signed-in state (displays the user email and Logout button).
Some developers may want to provide an account-picker, even for a single user:

To implement this, uncomment the provider.setCustomParameters({prompt: 'select_account'}); line in the web template as described earlier.
If there are multiple users, the account-picker dialog pops up (see below). If not signed-in yet, the user will be prompted. If already signed-in, the popup disappears, and the app goes into a signed-in state.

The signed-in state of Module 21 looks identical to Module 20's user interface:

The same is true for when an admin user has signed-in:

Unlike Module 21, Module 20 always accesses the logic for the web template content from the app (server-side code). A flaw of the Module 20 is that one visit is registered when the end-user hits the app the first time, and another one is registered when a user signs-in.
For Module 21, the login logic takes place in just the web template (client-side code). There is no required server-side trip to determine what content to display. The only call made to the server is the check for admin users after an end-user signs-in. This means that logins and logouts don't register additional visits, so the most recent visits list stays constant for user management actions. Notice the screenshots above display the same set of four visits across multiple user logins.
The Module 20 screenshots demonstrate the "double-visit bug" at the beginning of this codelab. Separate visits logs are displayed for each sign-in or sign-out action. Check the timestamps of the most recent visit for each screenshot displaying the chronological ordering.
Clean up
Общий
If you are done for now, we recommend you disable your App Engine app to avoid incurring billing. However if you wish to test or experiment some more, the App Engine platform has a free quota , and so as long as you don't exceed that usage tier, you shouldn't be charged. That's for compute, but there may also be charges for relevant App Engine services, so check its pricing page for more information. If this migration involves other Cloud services, those are billed separately. In either case, if applicable, see the "Specific to this codelab" section below.
For full disclosure, deploying to a Google Cloud serverless compute platform like App Engine incurs minor build and storage costs . Cloud Build has its own free quota as does Cloud Storage . Storage of that image uses up some of that quota. However, you might live in a region that does not have such a free tier, so be aware of your storage usage to minimize potential costs. Specific Cloud Storage "folders" you should review include:
-
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images -
console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com - The storage links above depend on your
PROJECT_IDandLOCation, for example, "us" if your app is hosted in the USA.
On the other hand, if you're not going to continue with this application or other related migration codelabs and want to delete everything completely, shut down your project .
Specific to this codelab
The services listed below are unique to this codelab. Refer to each product's documentation for more information:
- The App Engine Datastore service is provided by Cloud Datastore (Cloud Firestore in Datastore mode) which also has a free tier; see its pricing page for more information.
- Use of the Cloud Identity Platform has some level of "free," depending on which of its services you use. See its pricing page for more details.
- Use of the Cloud Resource Manager API is free for the most part per its pricing page .
Следующие шаги
Beyond this tutorial, other migration modules that focus on moving away from the legacy bundled services to consider include:
- Модуль 2 : миграция с App Engine
ndbна Cloud NDB - Modules 7-9 : migrate from App Engine Task Queue (push tasks) to Cloud Tasks
- Модули 12-13 : миграция с App Engine Memcache на Cloud Memorystore
- Модули 15-16 : миграция с App Engine Blobstore на Cloud Storage.
- Модули 18-19 : миграция с очереди задач App Engine (запросы на получение) на Cloud Pub/Sub.
App Engine is no longer the only serverless platform in Google Cloud. If you have a small App Engine app or one that has limited functionality and wish to turn it into a standalone microservice, or you want to break-up a monolithic app into multiple reusable components, these are good reasons to consider moving to Cloud Functions . If containerization has become part of your application development workflow, particularly if it consists of a CI/CD (continuous integration/continuous delivery or deployment) pipeline, consider migrating to Cloud Run . These scenarios are covered by the following modules:
- Migrate from App Engine to Cloud Functions: see Module 11
- Migrate from App Engine to Cloud Run: see Module 4 to containerize your app with Docker, or Module 5 to do it without containers, Docker knowledge, or
Dockerfiles
Switching to another serverless platform is optional, and we recommend considering the best options for your apps and use cases before making any changes.
Независимо от того, какой модуль миграции вы выберете следующим, весь контент Serverless Migration Station (практические занятия, видео, исходный код [при наличии]) доступен в его репозитории с открытым исходным кодом . README репозитория также содержится информация о том, какие миграции следует рассмотреть и в каком порядке следует выбирать модули миграции.
8. Additional resources
Listed below are additional resources for developers exploring this or related migration modules further. Below, you can provide feedback on this content, find links to the code, and various pieces of documentation you may find useful.
Codelabs issues/feedback
Если вы обнаружите какие-либо проблемы в этом практическом задании, пожалуйста, сначала найдите свою проблему, прежде чем сообщать о ней. Ссылки для поиска и создания новых проблем:
Миграционные ресурсы
Links to the repo folders for Module 20 (START) and Module 21 (FINISH) can be found in the table below.
Кодлаб | Python 2 | Python 3 |
(n/a) | ||
Module 21 (this codelab) |
Online references
Below are resources relevant for this tutorial:
Cloud Identity Platform and Cloud Marketplace
- Identity Platform product page
- Firebase Authentication
- Identity Platform and Firebase Auth product comparison page
- Identity Platform pricing information
- Identity Platform Quotas (and instrumentless usage)
- Identity Platform providers setup
- Cloud Marketplace product page
- Identity Platform page in Marketplace
Cloud Resource Manager, Cloud IAM, Firebase Admin SDK
- Resource Manager product page
- Resource Manager pricing information
- Resource Manager client library
- Cloud IAM overview (roles, allow-policy, etc.)
- Firebase Admin SDK (Python)
App Engine Users, App Engine NDB, Cloud NDB, Cloud Datastore
- App Engine Users overview
- App Engine NDB docs
- App Engine NDB repo
- Cloud NDB client library
- Cloud NDB repo
- Cloud Datastore product page
- Cloud Datastore pricing information
Other Migration Module references
- Migration Module introduction
- All "Serverless Migration Station" resources
- Migrating to Python 3 documentation
- Migration Module 17 "Using bundled services in 2nd-gen runtimes" codelab
- Migration Module 20 "Add App Engine Users service to Flask apps" codelab
App Engine migration
- Using 3rd-party libraries in Python 2 apps
- Changes to
app.yamlin 2nd-gen runtimes (Python 3) - Cloud NDB migration guide
- Cloud NDB migration content
App Engine platform
- Документация App Engine
- Среда выполнения Python 2 App Engine (стандартная среда)
- Using App Engine built-in libraries on Python 2 App Engine
- Среда выполнения Python 3 App Engine (стандартная среда)
- Различия между средами выполнения Python 2 и 3 App Engine (стандартная среда)
- Руководство по миграции с Python 2 на Python 3 App Engine (стандартная среда)
- Информация о ценах и квотах App Engine
- Запуск платформы App Engine второго поколения (2018)
- Сравнение платформ первого и второго поколений
- Долгосрочная поддержка устаревших сред выполнения.
- Documentation migration samples
- Community-contributed migration samples
Облачный SDK
- Google Cloud SDK
- Cloud SDK
gcloudcommand-line tool - Enabling (& disabling) Google APIs
- Cloud console API manager (enable/disable APIs)
- Enabling Google APIs with
gcloud - Listing Google APIs with
gcloud
Other Cloud information
- Python on Google Cloud
- Python client libraries documentation
- Python client libraries repositories
- "Always Free" tier
- Облачный SDK
- Cloud SDK
gcloudcommand-line tool - Вся документация Google Cloud
Видео
- Станция миграции бессерверных приложений
- Бессерверные экспедиции
- Подпишитесь на Google Cloud Tech
- Подпишитесь на Google Developers
Лицензия
Данная работа распространяется под лицензией Creative Commons Attribution 2.0 Generic.