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

1. Введение

Цели

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

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

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

Что вы узнаете

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

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

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

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

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

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

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

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

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

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

3. Создайте конфигурацию 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.

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

  1. Если у вас еще нет платежной учетной записи Cloud, первым делом необходимо создать новую учетную запись в 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 Console.
  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. Настройте сегмент облачного хранилища и правила его безопасности.

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

  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 для локального обслуживания своего приложения.

  1. Откройте новое окно терминала и из web каталога выполните следующую команду интерфейса командной строки Firebase, чтобы запустить эмулятор:
    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 и запустите сборку веб-пакета.

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

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

Что касается остальной части лаборатории кода, 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 для общих вариантов использования, а также полезного устранения неполадок и часто задаваемых вопросов.

,

1. Введение

Цели

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

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

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

Что вы узнаете

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

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

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

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

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

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

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

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

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 позволяет различать два настройки поставщика на следующих этапах этого CodeLab.

Инициализировать терраформ в каталоге

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

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

terraform init

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

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

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

  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 (прямо под блоком, который создает новый облачный проект), добавьте следующий блок ресурсов:

    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.

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

  • Вариант 1 (рекомендуется) : Настройка аутентификации Firebase в консоли, которая не требует GCIP.
    • Использование этой опции означает, что вам не нужно связывать свой новый проект с учетной записью облачных выставлений.
  • Вариант 2 : Установите аутентификацию Firebase через Terraform с использованием API Google Cloud Identity Platform (GCIP).
    • Использование этой опции означает, что вы должны связать свой новый проект с облачной биллинговой учетной записью, поскольку 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: Настройка аутентификации через API -интерфейсы Google Cloud Cloud Identity Platform (GCIP)

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

Включить выставление счетов через Terraform

  1. Если у вас еще нет учетной записи облачных платежей, первым шагом является создание новой учетной записи в облачной консоли Google . Когда вы это сделаете, обратите внимание на идентификатор его счетного счета . Идентификатор биллинга может быть расположен на биллинговой странице на биллинговом идентификаторе, связанном с вашим проектом. 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 . Перейдите в раздел APIS & Services в Cloud Console Google, чтобы сделать эту настройку.
  3. Поскольку вы впервые создаете идентификатор клиента для этого проекта, вам необходимо настроить экран согласия OAuth.
    1. Откройте страницу экрана согласия OAuth , а затем выберите только что созданный проект.
    2. Установите тип пользователя на внешний , а затем нажмите «Создать» .
    3. На следующем экране заполните следующее, а затем нажмите «Сохранить» и продолжить .
      • Установите общедоступное название приложения вашего приложения на что-то вроде FriendlyChat (это не должно быть во всем мире уникальным).
      • Выберите электронное письмо с поддержкой пользователя из раскрывающегося меню.
      • Введите электронное письмо для контактной информации разработчика .
    4. На следующих экранах завершите следующее:
      • Примите по умолчанию на странице Scopes , а затем нажмите «Сохранить» и продолжить .
      • Примите по умолчанию на странице Test Users , а затем нажмите «Сохранить» и продолжить .
      • Просмотрите резюме, а затем нажмите на панель инструментов .
      Configuring an OAuth2 client using the Google Cloud console
  4. Установите клиента OAuth на странице учетных данных , выполнив следующее:
    1. Нажмите «Создать учетные данные» и выберите идентификатор клиента OAuth .
    2. В раскрытии типа приложения выберите веб-приложение .
    3. В поле «Имя» введите имя вашего приложения, например, FriendlyChat (это не должно быть глобально уникальным).
    4. Позвольте URL вашего приложения использовать этого клиента OAuth, установив следующее:
      • Под авторизованным происхождением JavaScript нажмите « Добавить URI» и Enter
        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 и ее правила безопасности

Для веб-приложения этого CodeLab вы будете хранить сообщения между конечными пользователями в базе данных 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, такими как облачные функции. Для этого CodeLab вы можете использовать us-east1 (Южная Каролина) или использовать ближайший к вам регион (см. Места Cloud Firestore ).
  3. Каждый экземпляр базы данных Firestore, который доступен для Firebase, должен быть защищен правилами безопасности Firebase .

    Этот пример кода CodeLab предоставляет набор безопасных правил Firestore в файле firestore.rules , которые вы можете найти в корне web -каталога.
  4. Добавьте свой файл main.tf со следующими блоками ресурсов, чтобы сделать следующее:
    • Создайте набор правил правил безопасности Firebase из файла Local 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. Установите ведро облачного хранилища и его правила безопасности

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

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

    Обратите внимание, что облачное хранилище по умолчанию для вашего проекта предоставляется через Google App Engine и должно иметь то же место, что и ваша база данных Firestore. Смотрите местоположение приложения двигателя для получения дополнительной информации.

    Если вы хотите в вашем проекте несколько ведер, предоставите их с помощью ресурса 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 .

    Этот пример кода CodeLab предоставляет набор безопасных правил 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 к предоставлению ковша облачного хранилища по умолчанию и развернуть его правила безопасности.
  5. Убедитесь, что ведро предназначено и что его правила безопасности развернуты:
    1. В консоли Firebase найдите участок сборки на левой панели.
    2. Перейдите в раздел хранения , а затем нажмите на вкладку «Правила» .
    Verifying security rules using the Firebase console

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

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

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

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

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

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

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

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

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

Установите SDK Firebase и запустите сборку WebPack

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

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

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

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

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

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

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

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

  1. В консоли Firebase перейдите в настройки проекта .
  2. Прокрутите вниз до карты ваших приложений , а затем выберите ваше веб -приложение.
  3. Выберите Config на панели фрагмента SDK 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, добавить файл вашего приложения web/src/index.js следующим образом:

index.js

...

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

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

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

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

11. Реплицируйте вашу конфигурацию по средам

Terraform Excells при управлении несколькими аналогичными настроенными инфраструктурой (например, настройка проекта «Постановки Firebase», который похож на проект Prod).

In this codelab, you'll create a second Firebase project to be a staging environment.

To replicate an existing configuration to create this staging project, you have two options:

  • Option 1 : Make a copy of the Terraform configuration.
    This option offers the most flexibility for how much the replicated project can differ from the source project.
  • Option 2 : Reuse configurations with for_each .
    This option offers more code-reuse if each project should not differ in significant ways and you want to propagate changes to all projects at once.

Option 1: Make a copy of the Terraform configuration

This option offers the most flexibility for how much the replicated project can differ from the source project, such as having apps with different display names and staged rollouts.

  1. At the root of your web directory, create a new Terraform config file called main_staging.tf .
  2. Copy all the resource blocks from your main.tf file (except for the terraform and provider blocks), and then paste them into your main_staging.tf file.
  3. You then need to modify each of your replicated resource blocks in main_staging.tf for them to work with your staging project:
    • Resource labels: Use a new name to avoid conflict. For example, rename resource "google_project" "default" to resource "google_project" "staging" .
    • Resource references: Update each one. For example, update google_firebase_project.default.project to google_firebase_project.staging.project .
    You can find the complete configuration of a main_staging.tf file in this codelab's GitHub repository:

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

    If you want to use this config, make sure you do the following:
    1. Copy the config from main_staging-copypaste.tf , and then paste it into your main_staging.tf file.
    2. In your main_staging.tf file, do the following:
      • In the google_project resource block, update the name attribute, the project-id attribute, and (if you set up Authentication via Terraform) the billing_account attribute with your own values.
      • In the google_firebase_web_app resource block, update the display_name attribute with your own value.
      • In the google_firestore_database and google_app_engine_application resource blocks, update the location_id attributes with your own value.
    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. Run terraform apply to provision your new "staging" Firebase project and all its resources and enable its services.
  5. Verify that everything was provisioned and enabled as expected by checking them in the Firebase console as before.

Option 2: Reuse configurations with for_each

This option offers more code-reuse if each project should not differ in significant ways and you want to propagate changes to all projects at once. It uses the for_each meta-argument in the Terraform language.

  1. Open your main.tf file.
  2. Into each resource block that you want to replicate, add a for_each meta-argument, like so:

    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.
    
    You can find the complete configuration of a main.tf file that uses the for_each meta-argument in this codelab's GitHub repository:

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

    If you want to use this config, make sure you do the following:
    1. Copy the config from main-foreach.tf , and then paste it into your main.tf file.
    2. In your main.tf file, do the following:
      • In the google_project resource block, update the name attribute, the project-id attribute, and (if you set up Authentication via Terraform) the billing_account attribute with your own values.
      • In the google_firebase_web_app resource block, update the display_name attribute with your own value.
      • In the google_firestore_database and google_app_engine_application resource blocks, update the location_id attributes with your own value.
  3. Instead of applying this config right away, it's important to understand and fix a few things about how Terraform interprets this config compared to the existing infrastructure.
    1. Right now, if you applied this config that uses for_each , the resource addresses would look like the following:
      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"]
      
      However, the existing project you created in the first part of this codelab is known to Terraform as the following:
      google_project.default
      google_firebase_project.default
      google_firebase_android_app.default
      
    2. Run terraform plan to see what actions Terraform would take given the current state.

      The output should show that Terraform would delete the project you created in the first part of this codelab and create two new projects. This is because Terraform doesn't know that the project at the address google_project.default has been moved to the new address google_project.default["prod"] .
    3. To fix this, run the terraform state mv command:
      terraform state mv "google_project.default" "google_project.default[\"prod\"]"
      
    4. Similarly, to fix all the other resource blocks, run terraform state mv for google_firebase_project , google_firebase_web_app , and all the other resource blocks in your main.tf file.
    5. Now, if you run terraform plan again, it shouldn't show that Terraform would delete the project you created in the first part of this codelab.
  4. Run terraform apply to provision your new "staging" Firebase project and all its resources and enable its services.
  5. Verify that everything was provisioned and enabled as expected by checking them in the Firebase console as before.

12. Bonus step: Deploy your staging and prod apps

  1. In your app's codebase, change the firebase-config.js to use the Firebase config from your staging project instead.

    To remind yourself how to get your Firebase config and add it to your app, see the earlier step of this codelab, Add your Firebase configuration to your app.
  2. At the root of your web directory, run the following command to deploy your app to your staging Firebase project.
    firebase deploy --only hosting --project=<STAGING_PROJECT_ID>
    
  3. Open your staging app in the browser via the URL that's printed in the output of firebase deploy . Try signing in, sending messages, and uploading images.

    When you deploy an app to a Firebase project, it uses real Firebase resources, not emulated resources. As you interact with your staging app, you should see data and images appear in your staging project in the Firebase console.
  4. After testing your app in staging, change the firebase-config.js back to using the prod project's Firebase config (the first project that you created in this codelab).
  5. At the root of your web directory, run the following command to deploy your app to your production Firebase project.
    firebase deploy --only hosting --project=<PRODUCTION_PROJECT_ID>
    
  6. Open your production app in the browser via the URL that's printed in the output of firebase deploy . Try signing in, sending messages, and uploading images.

    You should see data and images appear in your production project in the Firebase console.
  7. When you're finished interacting with the two apps for this codelab, you can stop Firebase from serving them. Run the following command for each of your projects:
    firebase hosting:disable --project=<STAGING_PROJECT_ID>
    
    firebase hosting:disable --project=<PRODUCTION_PROJECT_ID>
    

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

You've used Terraform to configure a real-time chat web application! And you've followed best practices for development environments by creating separate Firebase projects for staging and prod.

Что мы рассмотрели

  • Using the Terraform CLI to manage cloud resources
  • Using Terraform to configure Firebase products (Authentication, Firestore, Cloud Storage, and Security Rules)
  • Running and testing a web app locally using the Firebase Local Emulator Suite
  • Importing Firebase into a web app
  • Using Terraform to replicate a configuration across multiple environments

For more information about Firebase and Terraform, visit our documentation . You can find a list of all Firebase products with Terraform support, sample Terraform configurations for common use cases, and helpful troubleshooting and FAQ.