Настраивайте проекты и продукты Firebase и управляйте ими через Terraform.

1. Введение

Цели

Вы можете использовать Terraform для настройки и управления проектом Firebase, включая программную настройку инфраструктуры и продуктов Firebase.

В этой лабораторной работе сначала описывается, как создать файл конфигурации Terraform для создания нового проекта Firebase, а затем — как настроить приложения и продукты Firebase, которые вы хотите использовать в этом проекте. Мы также рассмотрим основы командной строки Terraform, такие как предварительный просмотр вносимых изменений и их реализация.

Если вы хотели узнать, как настраивать и управлять проектами и продуктами Firebase с помощью Terraform, то эта практикум-практикум для вас!

Чему вы научитесь

  • Как создать файл конфигурации Terraform ( *.tf )
  • Как использовать команды Terraform CLI для управления инфраструктурой
  • Как изменить конфигурацию для обновления ресурсов и служб
  • Как применить вашу конфигурацию в реальном веб-приложении (так называемом Friendly Chat )
  • Как определить параллельные (и синхронизированные) конфигурации в различных средах (производство, подготовка и т. д.)

Что вам понадобится

Для успешного выполнения этой лабораторной работы вам необходимы базовые навыки работы с Terraform и его терминологией, включая следующие предварительные требования:

Эта лабораторная работа представляет собой реальный пример приложения, который вы сможете протестировать и использовать для взаимодействия с данными, предоставляемыми через Terraform. Для этого вам потребуется следующее:

  • Пример кода для веб-приложения — загрузите этот код на следующем этапе практического занятия.
  • Менеджер пакетов npm (который обычно идет в комплекте с Node.js ) — установите эти инструменты
  • Firebase CLI — установите этот CLI и войдите в систему.

2. Получите стартовый код

В этой лабораторной работе вы сможете протестировать ресурсы, предоставляемые через Terraform, на реальном веб-приложении. Мы рекомендуем сделать это, чтобы понять все этапы использования ресурсов, предоставляемых Terraform.

Клонируйте репозиторий GitHub кодовой лаборатории из командной строки:

git clone https://github.com/firebase/codelab-friendlychat-web

Кроме того, если у вас не установлен git, вы можете загрузить репозиторий в виде ZIP-файла .

3. Создайте конфигурацию Terraform

Настройка Terraform

  1. В кодовой базе загруженного примера приложения перейдите в корень web каталога.
  2. В корне этого каталога создайте файл конфигурации Terraform с именем main.tf со следующей начальной настройкой:

    main.tf
    # Terraform configuration to set up providers by version.
    terraform {
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 4.0"
        }
      }
    }
    
    # Configure the provider not to use the specified project for quota check.
    # This provider should only be used during project creation and initializing services.
    provider "google-beta" {
      alias                 = "no_user_project_override"
      user_project_override = false
    }
    
    # Configure the provider that uses the new project's quota.
    provider "google-beta" {
      user_project_override = true
    }
    

У каждого поставщика google-beta есть атрибут user_project_override , который определяет, как будет проверяться квота для операций из Terraform. Для предоставления большинства ресурсов следует использовать user_project_override = true , что означает проверку квоты по вашему собственному проекту Firebase. Однако, чтобы настроить новый проект для принятия проверок квот, сначала необходимо использовать user_project_override=false . Синтаксис alias Terraform позволяет различать настройки двух поставщиков на следующих этапах этой практической работы.

Инициализируйте Terraform в каталоге

Создание новой конфигурации в первый раз требует загрузки провайдера, указанного в конфигурации.

Чтобы выполнить эту инициализацию, выполните следующую команду из корня того же каталога, где находится ваш файл конфигурации main.tf :

terraform init

4. Создайте проект Firebase через Terraform.

Чтобы «создать проект Firebase», важно помнить, что каждый проект Firebase на самом деле является проектом Google Cloud, просто для него включены сервисы Firebase.

Добавьте блоки для базового проекта Google Cloud и API

  1. Во-первых, подготовьте базовый проект Google Cloud.

    Добавьте в файл конфигурации main.tf следующий блок ресурсов.

    Вам необходимо указать название вашего проекта (например, "Terraform FriendlyChat Codelab" ) и идентификатор проекта (например, "terraform-codelab-your-initials" ). Обратите внимание, что значение name используется только в интерфейсах Firebase и не отображается конечным пользователям. Значение project_id , однако, уникально идентифицирует ваш проект в Google, поэтому убедитесь, что вы указали уникальное значение. main.tf
    ...
    
    # Create a new Google Cloud project.
    resource "google_project" "default" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_YOUR_PROJECT>"
      project_id      = "<PROJECT_ID_OF_YOUR_PROJECT>"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
  2. Далее вам необходимо включить необходимые базовые API: API использования служб и API управления Firebase.

    Обычно это включение API выполняется «за кулисами», когда вы используете консоль Firebase для создания проекта Firebase, но Terraform необходимо явно указать, что необходимо выполнить это включение.

    В файл конфигурации main.tf (сразу под блоком, создающим новый проект Cloud), добавьте следующий блок ресурсов:

    main.tf
    ...
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "serviceusage" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "firebase" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    Включив API использования сервисов, ваш новый проект сможет принимать проверки квот! Поэтому для всех последующих выделений ресурсов и включения сервисов вам следует использовать провайдера с user_project_override (псевдоним не требуется).

Добавьте блок для включения служб Firebase

Последнее, что требуется для «создания проекта Firebase», — это включение служб Firebase в проекте.

Продолжая работу с файлом конфигурации main.tf , добавьте следующий блок ресурсов.

Как было упомянуто выше, обратите внимание, что этот блок ресурсов использует поставщика с user_project_override (псевдоним не требуется).

main.tf

...

# Enable Firebase services for the new project created above.
resource "google_firebase_project" "default" {
  provider = google-beta

  project = google_project.default.project_id

  # Wait until the required APIs are enabled.
  depends_on = [
    google_project_service.firebase,
    google_project_service.serviceusage,
  ]
}

В блоке ресурсов выше вы можете заметить предложение depends_on , которое предписывает Terraform дождаться включения базовых API. Без этого предложения Terraform не будет знать о зависимости и может столкнуться с ошибками при параллельном предоставлении ресурсов.

Применить конфигурацию

  1. Чтобы подготовить новые ресурсы и включить API, указанные в файле конфигурации, выполните следующую команду из корня того же каталога, где находится ваш файл main.tf (который должен быть web ):
    terraform apply
    
  2. В терминале Terraform выводит план действий, которые он будет выполнять.

    Если все выглядит так, как ожидалось, подтвердите действия, введя yes .

    main.tf
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
    
      # google_firebase_project.default will be created
      + resource "google_firebase_project" "default" {
          + display_name   = (known after apply)
          + id             = (known after apply)
          + project        = "terraform-friendlychat-codelab"
          + project_number = (known after apply)
        }
    
      # google_project.default will be created
      + resource "google_project" "default" {
          + auto_create_network = true
          + id                  = (known after apply)
          + labels              = {
              + "firebase" = "enabled"
            }
          + name                = "Terraform FriendlyChat Codelab"
          + number              = (known after apply)
          + project_id          = "terraform-friendlychat-codelab"
          + skip_delete         = (known after apply)
        }
    
      # google_project_service.firebase will be created
      + resource "google_project_service" "firebase" {
          + disable_on_destroy = false
          + id                 = (known after apply)
          + project            = "terraform-friendlychat-codelab"
          + service            = "firebase.googleapis.com"
        }
    
      # google_project_service.serviceusage will be created
      + resource "google_project_service" "serviceusage" {
          + disable_on_destroy = false
          + id                 = (known after apply)
          + project            = "terraform-friendlychat-codelab"
          + service            = "serviceusage.googleapis.com"
        }
    
    Plan: 4 to add, 0 to change, 0 to destroy.
    
    Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
    
      Enter a value: yes # <----
    

Обратите внимание: если вам нужно только просмотреть изменения, не применяя их, вы можете вместо этого использовать команду terraform plan .

Подтвердите изменения

После завершения работы Terraform вы можете проверить состояние всех предоставленных Terraform ресурсов и включенных служб, выполнив следующую команду:

terraform show

Вот пример того, что вы должны увидеть на печати. Ваш штат будет содержать значения, специфичные для вашего проекта.

# google_firebase_project.default:
resource "google_firebase_project" "default" {
    display_name   = "Terraform FriendlyChat Codelab"
    id             = "projects/terraform-friendlychat-codelab"
    project        = "terraform-friendlychat-codelab"
    project_number = "000000000"
}

# google_project.default:
resource "google_project" "default" {
    auto_create_network = true
    id                  = "projects/terraform-friendlychat-codelab"
    labels              = {
        "firebase" = "enabled"
    }
    name                = "Terraform FriendlyChat Codelab"
    number              = "000000000"
    project_id          = "terraform-friendlychat-codelab"
}

# google_project_service.firebase:
resource "google_project_service" "firebase" {
    disable_on_destroy = false
    id                 = "terraform-friendlychat-codelab/firebase.googleapis.com"
    project            = "terraform-friendlychat-codelab"
    service            = "firebase.googleapis.com"
}

# google_project_service.serviceusage:
resource "google_project_service" "serviceusage" {
    disable_on_destroy = false
    id                 = "terraform-friendlychat-codelab/serviceusage.googleapis.com"
    project            = "terraform-friendlychat-codelab"
    service            = "serviceusage.googleapis.com"
}

Кроме того, вы можете убедиться, что проект создан, просмотрев его в консоли Firebase .

The Terraform FriendlyChat Codelab project selected on the Firebase console

5. Зарегистрируйте свое приложение Firebase через Terraform.

Чтобы использовать Firebase, необходимо зарегистрировать все варианты вашего приложения для каждой платформы в проекте Firebase. В этой лабораторной работе вы будете использовать настоящее приложение для тестирования и взаимодействия с данными, предоставляемыми через Terraform. Поскольку это веб-приложение, вам нужно указать Terraform зарегистрировать веб-приложение Firebase в вашем новом проекте Firebase.

Добавьте блок для регистрации веб-приложения

Чтобы зарегистрировать веб-приложение в проекте Firebase, добавьте в файл main.tf следующий блок ресурсов.

Вам необходимо указать собственное display_name для вашего веб-приложения. Обратите внимание, что это имя используется только в интерфейсах Firebase и не отображается конечным пользователям.

main.tf

...

# Create a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "default" {
  provider = google-beta

  project      = google_firebase_project.default.project
  display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
  deletion_policy = "DELETE"
}

Применить конфигурацию

  1. Чтобы подготовить новый ресурс, выполните следующую команду из корня того же каталога, где находится ваш файл main.tf (который должен быть web ).
    terraform apply
    
    Обратите внимание, что эта команда не создаст новый проект Google Cloud заново. Terraform определит, что проект с указанным идентификатором уже существует, и сравнит его текущее состояние с данными в .tf файле, а затем внесет все обнаруженные изменения.
  2. Ознакомьтесь с распечатанным планом действий. Если всё выглядит так, как ожидалось, введите yes и нажмите Enter, чтобы подтвердить действия.

Подтвердите изменения

Вы можете проверить состояние только что выделенного ресурса, выполнив следующую команду:

terraform show

Вы также можете проверить, успешно ли приложение зарегистрировано в вашем проекте, просмотрев его в консоли Firebase. Перейдите в раздел «Настройки проекта» и прокрутите вниз до раздела «Ваши приложения» .

6. Настройте аутентификацию Firebase

Аутентификация — важная часть любого приложения. Чтобы позволить конечным пользователям входить в ваше веб-приложение с помощью своих учётных записей Google, вы можете включить аутентификацию Firebase и настроить вход с помощью Google.

Обратите внимание, что в этой лабораторной работе мы предоставляем два разных варианта настройки аутентификации Firebase:

  • Вариант 1 (рекомендуется) : настройка аутентификации Firebase в консоли, для которой не требуется GCIP.
    • Использование этой опции означает, что вам не придется связывать новый проект с учетной записью Cloud Billing.
  • Вариант 2 : настройка аутентификации Firebase через Terraform с использованием API Google Cloud Identity Platform (GCIP).
    • Использование этой опции означает, что вам придется связать свой новый проект с учетной записью Cloud Billing, поскольку GCIP требует, чтобы проект был включен в тарифный план Blaze.

Вариант 1: настройка аутентификации с помощью консоли Firebase

Чтобы настроить аутентификацию Firebase с помощью консоли Firebase, вашему проекту не обязательно быть на тарифном плане Blaze.

Вот как настроить аутентификацию Firebase и войти в систему с помощью Google:

  1. В консоли Firebase найдите раздел «Сборка» на левой панели.
  2. Нажмите «Аутентификация» , нажмите «Начать» , а затем нажмите вкладку «Метод входа» (или нажмите здесь , чтобы перейти туда напрямую).
  3. Нажмите Добавить нового поставщика и в разделе Дополнительные поставщики выберите Google .
  4. Активируйте переключатель Включить.
  5. Задайте публичное имя вашего приложения, например FriendlyChat (оно не обязательно должно быть глобально уникальным).
  6. Выберите адрес электронной почты службы поддержки проекта из раскрывающегося меню, а затем нажмите кнопку «Сохранить» . Configuring Firebase Auth on the Firebase console
  7. Вы должны увидеть Google в качестве включенного поставщика услуг входа. Firebase console Authentication page: Google sign-in enabled

Вариант 2: настройка аутентификации через Terraform с использованием API Google Cloud Identity Platform (GCIP)

Для настройки аутентификации Firebase через Terraform необходимо использовать API GCIP, что означает, что проект должен быть на тарифном плане Blaze. Чтобы обновить свой проект Firebase для использования тарифного плана Blaze, необходимо привязать к нему учётную запись Cloud Billing.

Включить биллинг через Terraform

  1. Если у вас ещё нет учётной записи Cloud Billing, первым шагом будет создание новой учётной записи в Google Cloud Console . При этом запишите идентификатор учётной записи . Идентификатор учётной записи можно найти на странице «Учётные записи» в разделе «Идентификатор учётной записи», связанном с вашим проектом. Enabling a billing account using the Google Cloud console
  2. Чтобы включить выставление счетов в вашем проекте через Terraform, добавьте атрибут billing_account в существующий ресурс google_project в файле main.tf :

    main.tf
    ...
    
    # Create a new Google Cloud project.
    resource "google_project" "default" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_YOUR_PROJECT>"
      project_id      = "<PROJECT_ID_OF_YOUR_PROJECT>"
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>" # Add this line with your Cloud Billing account ID
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    ...
    

Включите аутентификацию Firebase и войдите в систему с помощью Google через Terraform

  1. Чтобы обеспечить аутентификацию Firebase с помощью GCIP, добавьте в файл main.tf следующие блоки ресурсов:

    main.tf
    ...
    
    # Enable the Identity Toolkit API.
    resource "google_project_service" "auth" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      service =  "identitytoolkit.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Create an Identity Platform config.
    # Also, enable Firebase Authentication using Identity Platform (if Authentication isn't yet enabled).
    resource "google_identity_platform_config" "auth" {
      provider = google-beta
      project  = google_firebase_project.default.project
    
      # For example, you can configure to auto-delete anonymous users.
      autodelete_anonymous_users = true
    
      # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
      depends_on = [
        google_project_service.auth,
      ]
    }
    
  2. Для включения входа через Google требуется клиент OAuth . Для настройки перейдите в раздел «API и сервисы» консоли Google Cloud.
  3. Поскольку вы впервые создаете идентификатор клиента для этого проекта, вам необходимо настроить экран согласия OAuth.
    1. Откройте страницу экрана согласия OAuth , а затем выберите проект, который вы только что создали.
    2. Установите Тип пользователя на Внешний , а затем нажмите Создать .
    3. На следующем экране выполните следующие действия, а затем нажмите кнопку Сохранить и продолжить .
      • Задайте публичное имя вашего приложения, например FriendlyChat (оно не обязательно должно быть глобально уникальным).
      • Выберите адрес электронной почты службы поддержки пользователей из раскрывающегося меню.
      • Введите адрес электронной почты для контактной информации разработчика .
    4. На следующих экранах выполните следующие действия:
      • Примите значения по умолчанию на странице «Области действия» , а затем нажмите «Сохранить и продолжить» .
      • Примите значения по умолчанию на странице Тестовые пользователи , а затем нажмите Сохранить и продолжить .
      • Просмотрите сводку, а затем нажмите Вернуться на панель управления .
      Configuring an OAuth2 client using the Google Cloud console
  4. Настройте клиент OAuth на странице «Учетные данные» , выполнив следующие действия:
    1. Нажмите Создать учетные данные и выберите Идентификатор клиента OAuth .
    2. В раскрывающемся списке Тип приложения выберите Веб-приложение .
    3. В поле «Имя» введите имя вашего приложения, например, FriendlyChat (оно не обязательно должно быть глобально уникальным).
    4. Разрешите URL-адресу вашего приложения использовать этот клиент OAuth, установив следующее:
      • В разделе «Авторизованные источники JavaScript» нажмите «Добавить URI» и введите
        https://<PROJECT_ID>.firebaseapp.com , где <PROJECT_ID> — это идентификатор проекта, который вы указали в main.tf .
      • В разделе «Авторизованные URI перенаправления» нажмите «Добавить URI» и введите
        https://<PROJECT_ID>.firebaseapp.com/__/auth/handler , где <PROJECT_ID> — это идентификатор проекта, который вы указали в main.tf .
    5. Нажмите «Сохранить» .
    Obtaining the OAuth2 Client ID and secret from the Google Cloud console Credentials page
  5. Чтобы включить вход через Google с использованием идентификатора клиента OAuth и секретного ключа клиента, добавьте в файл main.tf следующий блок:

    main.tf
    ...
    
    variable "oauth_client_secret" {
      type = string
    
      description = "OAuth client secret. For this codelab, you can pass in this secret through the environment variable TF_VAR_oauth_client_secret. In a real app, you should use a secret manager service."
    
      sensitive = true
    }
    
    resource "google_identity_platform_default_supported_idp_config" "google_sign_in" {
      provider = google-beta
      project  = google_firebase_project.default.project
    
      enabled       = true
      idp_id        = "google.com"
      client_id     = "<YOUR_OAUTH_CLIENT_ID>"
      client_secret = var.oauth_client_secret
    
      depends_on = [
         google_identity_platform_config.auth
      ]
    }
    

Применить конфигурацию

  1. Чтобы настроить аутентификацию в соответствии с вашей конфигурацией, выполните следующие команды из корня того же каталога, где находится ваш файл main.tf (который должен быть web ):
    export TF_VAR_oauth_client_secret="<YOUR_OAUTH_CLIENT_SECRET>"
    
    terraform apply
    
    Обратите внимание, что выполнение terraform apply не приведёт к повторному созданию нового проекта Google Cloud. Terraform обнаружит, что проект с указанным идентификатором уже существует, и сравнит его текущее состояние с данными в .tf файле. Затем он внесет все обнаруженные изменения.
  2. Ознакомьтесь с распечатанным планом действий. Если всё выглядит так, как ожидалось, введите yes и нажмите Enter, чтобы подтвердить действия.

Подтвердите изменения

  1. В консоли Firebase найдите раздел «Сборка» на левой панели.
  2. Нажмите «Аутентификация» , а затем нажмите вкладку «Метод входа» (или нажмите здесь , чтобы перейти туда).
  3. Вы должны увидеть Google в качестве включенного поставщика услуг входа. Firebase console Authentication page: Google sign-in enabled

7. Настройте базу данных Firestore и ее правила безопасности.

В веб-приложении этой лабораторной работы вы будете хранить сообщения между конечными пользователями в базе данных Firestore.

  1. Чтобы включить требуемые API и подготовить экземпляр базы данных, добавьте в файл main.tf следующие блоки ресурсов:

    main.tf
    ...
    
    # Enable required APIs for Cloud Firestore.
    resource "google_project_service" "firestore" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      for_each = toset([
        "firestore.googleapis.com",
        "firebaserules.googleapis.com",
      ])
      service = each.key
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Provision the Firestore database instance.
    resource "google_firestore_database" "default" {
      provider                    = google-beta
    
      project                     = google_firebase_project.default.project
      name                        = "(default)"
      # See available locations:
      # https://firebase.google.com/docs/firestore/locations
      location_id                 = "<NAME_OF_DESIRED_REGION>"
      # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs,
      # authentication, and Firebase Security Rules.
      type                        = "FIRESTORE_NATIVE"
      concurrency_mode            = "OPTIMISTIC"
    
      depends_on = [
        google_project_service.firestore
      ]
    }
    
  2. Измените <NAME_OF_DESIRED_REGION> на регион, в котором вы хотите разместить базу данных.

    При разработке производственного приложения вам понадобится регион, близкий к большинству пользователей и совпадающий с другими сервисами Firebase, такими как Cloud Functions. Для этой практической работы вы можете использовать us-east1 (Южная Каролина) или ближайший к вам регион (см. раздел «Расположение Cloud Firestore »).
  3. Каждый экземпляр базы данных Firestore, доступный для Firebase, должен быть защищен правилами безопасности Firebase .

    В примере кода этой лабораторной работы представлен набор безопасных правил Firestore в файле firestore.rules , который можно найти в корне web каталога.
  4. Добавьте в файл main.tf следующие блоки ресурсов, чтобы выполнить следующее:
    • Создайте набор правил безопасности Firebase из локального файла firestore.rules .
    • Выпустите набор правил для экземпляра Firestore.
    Обратите внимание, что эти блоки ресурсов выполняют функцию, эквивалентную нажатию кнопки «Опубликовать» в консоли Firebase или запуску firebase deploy --only firestore:rules .

    main.tf
    ...
    
    # Create a ruleset of Firestore Security Rules from a local file.
    resource "google_firebaserules_ruleset" "firestore" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      source {
        files {
          name = "firestore.rules"
          # Write security rules in a local file named "firestore.rules".
          # Learn more: https://firebase.google.com/docs/firestore/security/get-started
          content = file("firestore.rules")
        }
      }
    
      # Wait for Firestore to be provisioned before creating this ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    }
    
    # Release the ruleset for the Firestore instance.
    resource "google_firebaserules_release" "firestore" {
      provider     = google-beta
    
      name         = "cloud.firestore"  # must be cloud.firestore
      ruleset_name = google_firebaserules_ruleset.firestore.name
      project      = google_firebase_project.default.project
    
      # Wait for Firestore to be provisioned before releasing the ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    
      lifecycle {
        replace_triggered_by = [
          google_firebaserules_ruleset.firestore
        ]
      }
    }
    
  5. Запустите terraform apply , чтобы подготовить базу данных Firestore и развернуть ее правила безопасности.
  6. Убедитесь, что база данных подготовлена и ее правила безопасности развернуты:
    1. В консоли Firebase найдите раздел «Сборка» на левой панели.
    2. Перейдите в раздел «База данных Firestore» , а затем нажмите вкладку «Правила» .
    Verifying Cloud Firestore rules using the Firebase console

8. Настройте контейнер облачного хранилища и его правила безопасности.

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

  1. Чтобы включить требуемые API и подготовить контейнер Cloud Storage по умолчанию, добавьте в файл main.tf следующие блоки ресурсов.

    Обратите внимание, что контейнер Cloud Storage по умолчанию для вашего проекта предоставляется через Google App Engine и должен располагаться в том же месте, что и ваша база данных Firestore. Подробнее см. в разделе «Расположение в App Engine» .

    Если вам нужно несколько контейнеров в вашем проекте, подготовьте их с помощью ресурса google_storage_bucket (не показан в этой кодовой работе).

    main.tf
    ...
    
    # Enable required APIs for Cloud Storage for Firebase.
    resource "google_project_service" "storage" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      for_each = toset([
        "firebasestorage.googleapis.com",
        "storage.googleapis.com",
      ])
      service = each.key
    
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Provision the default Cloud Storage bucket for the project via Google App Engine.
    resource "google_app_engine_application" "default" {
      provider    = google-beta
    
      project     = google_firebase_project.default.project
      # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
      # This will set the location for the default Storage bucket and the App Engine App.
      location_id = "<NAME_OF_DESIRED_REGION_FOR_DEFAULT_BUCKET>"  # Must be in the same location as Firestore (above)
    
      # Wait until Firestore is provisioned first.
      depends_on = [
        google_firestore_database.default
      ]
    }
    
    # Make the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
    resource "google_firebase_storage_bucket" "default-bucket" {
      provider  = google-beta
    
      project   = google_firebase_project.default.project
      bucket_id = google_app_engine_application.default.default_bucket
    }
    
  2. Каждый контейнер облачного хранилища, доступный Firebase, должен быть защищен правилами безопасности Firebase .

    В примере кода этой лабораторной работы представлен набор безопасных правил Firestore в файле storage.rules , который можно найти в корне web каталога.
  3. Добавьте в файл main.tf следующие блоки ресурсов, чтобы выполнить следующее:
    • Создайте набор правил безопасности Firebase из локального файла.
    • Освободите набор правил для контейнера хранения.
    Обратите внимание, что эти блоки ресурсов выполняют функцию, эквивалентную нажатию кнопки «Опубликовать» в консоли Firebase или запуску firebase deploy --only storage .

    main.tf
    ...
    
    # Create a ruleset of Cloud Storage Security Rules from a local file.
    resource "google_firebaserules_ruleset" "storage" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      source {
        files {
          # Write security rules in a local file named "storage.rules".
          # Learn more: https://firebase.google.com/docs/storage/security/get-started
          name    = "storage.rules"
          content = file("storage.rules")
        }
      }
    
      # Wait for the default Storage bucket to be provisioned before creating this ruleset.
      depends_on = [
        google_firebase_storage_bucket.default-bucket,
      ]
    }
    
    # Release the ruleset to the default Storage bucket.
    resource "google_firebaserules_release" "default-bucket" {
      provider     = google-beta
    
      name         = "firebase.storage/${google_app_engine_application.default.default_bucket}"
      ruleset_name = "projects/${google_firebase_project.default.project}/rulesets/${google_firebaserules_ruleset.storage.name}"
      project      = google_firebase_project.default.project
    
      lifecycle {
        replace_triggered_by = [
          google_firebaserules_ruleset.storage
        ]
      }
    }
    
  4. Запустите terraform apply , чтобы подготовить контейнер Cloud Storage по умолчанию и развернуть его правила безопасности.
  5. Убедитесь, что контейнер подготовлен и его правила безопасности развернуты:
    1. В консоли Firebase найдите раздел «Сборка» на левой панели.
    2. Перейдите в раздел Хранилище , а затем нажмите вкладку Правила .
    Verifying security rules using the Firebase console

9. Запустите приложение локально

Теперь вы готовы к первому запуску своего веб-приложения! Для локального обслуживания приложения вам понадобится эмулятор Firebase Hosting .

  1. Откройте новое окно терминала и из web каталога выполните следующую команду Firebase CLI, чтобы запустить эмулятор:
    firebase emulators:start --project=<PROJECT_ID>
    
  2. В браузере откройте веб-приложение по локальному URL-адресу, возвращенному CLI (обычно http://localhost:5000 ).

Вы должны увидеть пользовательский интерфейс вашего приложения FriendlyChat, который (пока!) не работает. Приложение пока не подключено к Firebase, но после выполнения следующих шагов этой практической работы оно будет подключено!

Обратите внимание: всякий раз, когда вы вносите изменения в свое веб-приложение (например, на следующих этапах этой лабораторной работы), обновите страницу браузера, чтобы обновить локальный URL-адрес с учетом этих изменений.

10. Установка, настройка и инициализация Firebase

Чтобы приложение работало с Firebase, вашему приложению необходим Firebase SDK и конфигурация Firebase для вашего проекта Firebase.

Пример кода для этой лабораторной работы уже представляет собой работающее приложение со всеми зависимостями и необходимыми функциями для использования различных продуктов Firebase. Вы можете посмотреть файлы web/package.json и web/src/index.js чтобы увидеть, что уже сделано.

Несмотря на то, что пример кода в основном завершен, вам все еще нужно сделать несколько вещей, чтобы запустить приложение, в том числе: установить Firebase SDK, начать сборку, добавить конфигурацию Firebase в свое приложение и, наконец, инициализировать Firebase.

Установите Firebase SDK и начните сборку Webpack.

Чтобы начать сборку приложения, вам необходимо выполнить несколько команд.

  1. Откройте новое окно терминала.
  2. Убедитесь, что вы находитесь в корне web каталога.
  3. Запустите npm install , чтобы загрузить Firebase SDK.
  4. Запустите npm update , чтобы обновить все зависимости.
  5. Запустите npm run start , чтобы запустить webpack.

Для оставшейся части кодовой лаборатории Webpack теперь будет постоянно пересобирать ваш исходный код.

Добавьте конфигурацию Firebase в свое приложение

Вам также необходимо добавить конфигурацию Firebase в свое приложение, чтобы Firebase SDK знали, какой проект Firebase вы хотите использовать.

Для этой лабораторной работы у вас есть два варианта получения конфигурации Firebase:

  • Вариант 1 : Получите конфигурацию Firebase из консоли Firebase.
  • Вариант 2 : Получите конфигурацию Firebase через Terraform.

Вариант 1: получить конфигурацию из консоли Firebase и добавить ее в свою кодовую базу

  1. В консоли Firebase перейдите в настройки проекта .
  2. Прокрутите страницу вниз до карточки Ваши приложения , а затем выберите свое веб-приложение.
  3. Выберите Config на панели фрагментов Firebase SDK, а затем скопируйте фрагмент конфигурации.
  4. Вставьте свою конфигурацию в файл web/src/firebase-config.js вашего приложения, например так:

    firebase-config.js
    ...
    
    const config = {
      apiKey: "<API_KEY>",
      authDomain: "<PROJECT_ID>.firebaseapp.com",
      projectId: "<PROJECT_ID>",
      storageBucket: "<PROJECT_ID>.appspot.com",
      messagingSenderId: "<SENDER_ID>",
      appId: "<APP_ID>",
      measurementId: "<G-MEASUREMENT_ID>",
    };
    
    ...
    

Вариант 2: получить конфигурацию через Terraform и добавить ее в свою кодовую базу

Альтернативно, вы можете получить конфигурацию Firebase через Terraform как выходное значение в CLI.

  1. В файле main.tf найдите блок ресурсов google_firebase_web_app (блок, который зарегистрировал веб-приложение в вашем проекте).
  2. Сразу после этого блока добавьте следующие блоки:

    main.tf
    ...
    
    data "google_firebase_web_app_config" "default" {
      provider     = google-beta
      project      = google_firebase_project.default.project
      web_app_id   = google_firebase_web_app.default.app_id
    }
    
    output "friendlychat_web_app_config" {
      value = {
        projectId         = google_firebase_project.default.project
        appId             = google_firebase_web_app.default.app_id
        apiKey            = data.google_firebase_web_app_config.default.api_key
        authDomain        = data.google_firebase_web_app_config.default.auth_domain
        storageBucket     = lookup(data.google_firebase_web_app_config.default, "storage_bucket", "")
        messagingSenderId = lookup(data.google_firebase_web_app_config.default, "messaging_sender_id", "")
        measurementId     = lookup(data.google_firebase_web_app_config.default, "measurement_id", "")
      }
    }
    
    ...
    
  3. Поскольку блок data и блок output не предназначены для какого-либо изменения инфраструктуры, вам нужно только выполнить следующие команды.
    1. Чтобы загрузить конфигурацию Firebase вашего веб-приложения в состояние Terraform вашего каталога, выполните следующую команду:
      terraform refresh
      
    2. Чтобы распечатать значения конфигурации Firebase, выполните следующую команду:
      terraform output –json
      
      Ниже приведён пример выходных данных конфигурации. Выводимые данные будут содержать значения вашего проекта и приложения.
      {
        "friendlychat_web_app_config": {
          "sensitive": false,
          "type": [
            "object",
            {
              "apiKey": "string",
              "appId": "string",
              "authDomain": "string",
              "measurementId": "string",
              "messagingSenderId": "string",
              "projectId": "string",
              "storageBucket": "string"
            }
          ],
          "value": {
            "apiKey": "<API_KEY>",
            "appId": "<APP_ID>",
            "authDomain": "<PROJECT_ID>.firebaseapp.com",
            "measurementId": "<G-MEASUREMENT_ID>",
            "messagingSenderId": "<SENDER_ID>",
            "projectId": "<PROJECT_ID>",
            "storageBucket": "<PROJECT_ID>.appspot.com"
          }
        }
      }
      
  4. Скопируйте значения из карты value .
  5. Вставьте эти значения (вашу конфигурацию) в файл web/src/firebase-config.js вашего приложения, например так:

    firebase-config.js
    ...
    
    const config = {
      apiKey: "<API_KEY>",
      appId: "<APP_ID>",
      authDomain: "<PROJECT_ID>.firebaseapp.com",
      measurementId: "<G-MEASUREMENT_ID>",
      messagingSenderId: "<SENDER_ID>",
      projectId: "<PROJECT_ID>",
      storageBucket: "<PROJECT_ID>.appspot.com",
    };
    
    ...
    

Инициализируйте Firebase в вашем приложении

Наконец, чтобы инициализировать Firebase, добавьте в файл web/src/index.js вашего приложения следующее:

index.js

...

const firebaseAppConfig = getFirebaseConfig();
initializeApp(firebaseAppConfig);

Попробуйте ваше приложение

Теперь, когда все настроено для Firebase, вы можете опробовать свое функциональное веб-приложение.

  1. Обновите браузер, обслуживающий ваше приложение.
  2. Теперь вы сможете войти в систему через Google и начать отправлять сообщения в чат. Если у вас есть изображения, вы даже можете их загрузить!

11. Копируйте конфигурацию в разные среды

Terraform отлично справляется с управлением несколькими одинаково настроенными инфраструктурами (например, настройкой промежуточного проекта Firebase, похожего на производственный проект).

В этой лабораторной работе вы создадите второй проект Firebase, который будет промежуточной средой.

Чтобы скопировать существующую конфигурацию для создания этого промежуточного проекта, у вас есть два варианта:

  • Вариант 1 : Создайте копию конфигурации Terraform.
    Этот вариант обеспечивает наибольшую гибкость в плане отличия реплицированного проекта от исходного проекта.
  • Вариант 2 : повторное использование конфигураций с for_each .
    Этот вариант обеспечивает больше возможностей повторного использования кода, если каждый проект не должен существенно отличаться и вы хотите распространить изменения на все проекты одновременно.

Вариант 1: Создайте копию конфигурации Terraform

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

  1. В корне вашего web каталога создайте новый файл конфигурации Terraform с именем main_staging.tf .
  2. Скопируйте все блоки ресурсов из файла main.tf (за исключением блоков terraform и provider ), а затем вставьте их в файл main_staging.tf .
  3. Затем вам необходимо изменить каждый из реплицированных блоков ресурсов в main_staging.tf , чтобы они работали с вашим промежуточным проектом:
    • Метки ресурсов: используйте новое имя, чтобы избежать конфликтов. Например, переименуйте resource "google_project" "default" в resource "google_project" "staging" .
    • Ссылки на ресурсы: обновите каждую из них. Например, измените google_firebase_project.default.project на google_firebase_project.staging.project .
    Полную конфигурацию файла main_staging.tf можно найти в репозитории GitHub этой кодовой лаборатории:

    web/terraform-checkpoints/replicate-config/main_staging-copypaste.tf

    Если вы хотите использовать эту конфигурацию, убедитесь, что вы выполнили следующее:
    1. Скопируйте конфигурацию из main_staging-copypaste.tf и вставьте ее в файл main_staging.tf .
    2. В файле main_staging.tf выполните следующие действия:
      • В блоке ресурсов google_project обновите атрибут name , атрибут project-id и (если вы настроили аутентификацию через Terraform) атрибут billing_account , указав собственные значения.
      • В блоке ресурсов google_firebase_web_app обновите атрибут display_name , указав собственное значение.
      • В блоках ресурсов google_firestore_database и google_app_engine_application обновите атрибуты location_id , указав собственное значение.
    main_staging.tf
    # Create a new Google Cloud project.
    resource "google_project" "staging" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_STAGING_PROJECT>"
      project_id      = "<PROJECT_ID_OF_STAGING_PROJECT"
      # Required if you want to set up Authentication via Terraform
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "staging_serviceusage" {
      provider = google-beta.no_user_project_override
    
      project = google_project.staging.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "staging_firebase" {
      provider = google-beta.no_user_project_override
    
      project = google_project.staging.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable Firebase services for the new project created above.
    resource "google_firebase_project" "staging" {
      provider = google-beta
    
      project = google_project.staging.project_id
    
      # Wait until the required APIs are enabled.
      depends_on = [
        google_project_service.staging_serviceusage,
        google_project_service.staging_firebase,
      ]
    }
    
    # Create a Firebase Web App in the new project created above.
    resource "google_firebase_web_app" "staging" {
      provider = google-beta
    
      project      = google_firebase_project.staging.project
      display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
      deletion_policy = "DELETE"
    }
    
  4. Запустите terraform apply , чтобы подготовить новый «промежуточный» проект Firebase и все его ресурсы, а также включить его службы.
  5. Убедитесь, что все подготовлено и включено, как и ожидалось, проверив их в консоли Firebase , как и раньше.

Вариант 2: повторное использование конфигураций с for_each

Этот вариант обеспечивает более эффективное повторное использование кода, если каждый проект не должен существенно отличаться, и вы хотите распространить изменения на все проекты одновременно. Он использует метааргумент for_each в языке Terraform.

  1. Откройте файл main.tf
  2. В каждый блок ресурсов, который вы хотите реплицировать, добавьте метааргумент for_each , например:

    main.tf
    # Create new Google Cloud projects.
    resource "google_project" "default" {
      provider        = google-beta.no_user_project_override
      name            = each.value
      # Create a unique project ID for each project, with each ID starting with <PROJECT_ID>.
      project_id      = "<PROJECT_ID>-${each.key}"
      # Required if you want to set up Authentication via Terraform
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>"
    
      # Required for the projects to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    
      for_each = {
        prod    = "<PROJECT_NAME_OF_PROD_PROJECT>"
        staging = "<PROJECT_NAME_OF_STAGING_PROJECT>"
      }
    }
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "serviceusage" {
      provider = google-beta.no_user_project_override
      for_each = google_project.default
    
      project = each.value.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "firebase" {
      provider = google-beta.no_user_project_override
      for_each = google_project.default
    
      project = each.value.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable Firebase services for each of the new projects created above.
    resource "google_firebase_project" "default" {
      provider = google-beta
      for_each = google_project.default
    
      project = each.value.project_id
    
      depends_on = [
        google_project_service.serviceusage,
        google_project_service.firebase,
      ]
    }
    
    # Create a Firebase Web App in each of the new projects created above.
    resource "google_firebase_web_app" "default" {
      provider = google-beta
      for_each = google_firebase_project.default
    
      project      = each.value.project
      # The Firebase Web App created in each project will have the same display name.
      display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
      deletion_policy = "DELETE"
    }
    
    
    # NOTE: For this codelab, we recommend setting up Firebase Authentication
    # using the Firebase console. However, if you set up Firebase Authentication
    # using Terraform, copy-paste from your main.tf the applicable blocks.
    # Make sure to add the `for_each` meta-argument into each block.
    
    
    # Copy-paste from your main.tf file the applicable resource blocks
    # for setting up Cloud Firestore (including rules) and
    # for setting up Cloud Storage for Firebase (including rules).
    # Make sure to add the `for_each` meta-argument into each block.
    
    Полную конфигурацию файла main.tf , который использует метааргумент for_each можно найти в репозитории GitHub этой кодовой лаборатории:

    web/terraform-checkpoints/replicate-config/main-foreach.tf

    Если вы хотите использовать эту конфигурацию, убедитесь, что вы выполнили следующее:
    1. Скопируйте конфигурацию из main-foreach.tf и вставьте ее в файл main.tf
    2. В вашем файле main.tf сделайте следующее:
      • В блоке ресурсов google_project обновите атрибут name , атрибут project-id и (если вы настроили аутентификацию через Terraform) атрибут billing_account со своими собственными значениями.
      • В блоке ресурса google_firebase_web_app обновите атрибут display_name со своим собственным значением.
      • В блоках ресурсов google_firestore_database и google_app_engine_application обновите атрибуты location_id с вашим собственным значением.
  3. Вместо того, чтобы сразу применять эту конфигурацию, важно понимать и исправить некоторые вещи о том, как Terraform интерпретирует эту конфигурацию по сравнению с существующей инфраструктурой.
    1. Прямо сейчас, если бы вы применили эту конфигурацию, которая использует for_each , адреса ресурса выглядели бы следующим образом:
      google_project.default["prod"]
      google_project.default["staging"]
      google_firebase_project.default["prod"]
      google_firebase_project.default["staging"]
      google_firebase_web_app.default["prod"]
      google_firebase_web_app.default["staging"]
      
      Тем не менее, существующий проект, который вы создали в первой части этого CodeLab, известен Terraform как следующее:
      google_project.default
      google_firebase_project.default
      google_firebase_android_app.default
      
    2. Запустите terraform plan чтобы увидеть, какие действия Terraform предпримет с учетом текущего состояния.

      Вывод должен показать, что Terraform удалит проект, который вы создали в первой части этого CodeLab, и создаст два новых проекта. Это связано с тем, что Terraform не знает, что проект по адресу google_project.default был перенесен на новый адрес google_project.default["prod"] .
    3. Чтобы исправить это, запустите команду terraform state mv :
      terraform state mv "google_project.default" "google_project.default[\"prod\"]"
      
    4. Точно так же, чтобы исправить все другие блоки ресурсов, запустите terraform state mv для google_firebase_project , google_firebase_web_app и всех других блоков ресурсов в вашем файле main.tf
    5. Теперь, если вы снова запустите terraform plan , он не должен показывать, что Terraform удалит проект, который вы создали в первой части этого CodeLab.
  4. Запустите terraform apply к предоставлению вашего нового проекта «Постановки» Firebase и всех его ресурсов и обеспечить его услуги.
  5. Убедитесь, что все было подготовлено и включено, как и ожидалось, проверив их в консоли Firebase , как и раньше.

12. Бонусный шаг: разверните приложения для постановки и Prod

  1. В кодовой базе вашего приложения измените firebase-config.js , чтобы использовать конфигурацию Firebase из вашего проекта по стадии.

    Чтобы напомнить себе, как получить конфигурацию Firebase и добавить ее в свое приложение, см. Более ранний шаг этого CodeLab, добавьте свою конфигурацию Firebase в ваше приложение.
  2. В корне вашего web -каталога запустите следующую команду, чтобы развернуть ваше приложение для вашего проекта «Постановка Firebase».
    firebase deploy --only hosting --project=<STAGING_PROJECT_ID>
    
  3. Откройте приложение для постановки в браузере с помощью URL -адреса, которое напечатано на выводе firebase deploy . Попробуйте войти, отправлять сообщения и загружать изображения.

    Когда вы разместите приложение в проект Firebase, оно использует реальные ресурсы Firebase, а не эмулируемые ресурсы. Когда вы взаимодействуете со своим приложением для постановки, вы должны видеть, что данные и изображения появляются в вашем проекте «Проект» в консоли Firebase.
  4. После тестирования вашего приложения в постановке измените firebase-config.js на использование конфигурации Firebase проекта Prod (первый проект, который вы создали в этом CodeLab).
  5. В корне вашего web -каталога запустите следующую команду для развертывания вашего приложения в проект Production Firebase.
    firebase deploy --only hosting --project=<PRODUCTION_PROJECT_ID>
    
  6. Откройте свое производственное приложение в браузере через URL, который напечатан на выводе firebase deploy . Попробуйте войти, отправлять сообщения и загружать изображения.

    Вы должны видеть данные и изображения, появляющиеся в вашем производственном проекте в консоли Firebase.
  7. Когда вы закончите взаимодействовать с двумя приложениями для этого CodeLab, вы можете остановить Firebase от обслуживания их. Запустите следующую команду для каждого из ваших проектов:
    firebase hosting:disable --project=<STAGING_PROJECT_ID>
    
    firebase hosting:disable --project=<PRODUCTION_PROJECT_ID>
    

13. Поздравляю!

Вы использовали Terraform для настройки веб-приложения чата в реальном времени! И вы следили за лучшими практиками для среды разработки, создавая отдельные проекты Firebase для постановки и Prod.

То, что мы покрыли

  • Использование Terraform CLI для управления облачными ресурсами
  • Использование Terraform для настройки продуктов Firebase (аутентификация, Firestore, облачное хранилище и правила безопасности)
  • Запуск и тестирование веб -приложения локально с использованием локального эмулятора Firebase
  • Импорт Firebase в веб -приложение
  • Использование Terraform для воспроизведения конфигурации в нескольких средах

Для получения дополнительной информации о Firebase и Terraform посетите нашу документацию . Вы можете найти список всех продуктов Firebase с поддержкой Terraform, образец конфигураций Terraform для общих вариантов использования, а также полезного устранения неполадок и часто задаваемых вопросов.