Начните работу с Terraform и Firebase

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

Базовый рабочий процесс использования Terraform с Firebase включает следующее:

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

  • Использование команд gcloud CLI , взаимодействующих с Terraform, для подготовки инфраструктуры, указанной в файле .tf .

Что вы можете сделать с Terraform и Firebase?

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

  • Удалите и измените существующую инфраструктуру с помощью Terraform.

  • Управляйте конфигурацией и задачами конкретного продукта с помощью Terraform, например:

    • Включение поставщиков Firebase Authentication .
    • Создание сегментов Cloud Storage или экземпляров базы данных и развертывание для них Firebase Security Rules .

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



Общий рабочий процесс использования Terraform с Firebase

Предварительные условия

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


Шаг 1. Создайте и настройте файл конфигурации Terraform.

Конфигурационный файл Terraform состоит из двух основных разделов (которые подробно описаны ниже):

Настройте своего provider

Настройка provider требуется независимо от того, какие продукты или услуги Firebase задействованы.

  1. Создайте файл конфигурации Terraform (например, файл main.tf ) в своем локальном каталоге.

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

    У вас есть следующие варианты включения настройки provider в остальную часть вашей конфигурации Terraform:

    • Вариант 1. Включите его в начало одного файла конфигурации Terraform .tf (как показано в этом руководстве).

      • Используйте этот вариант, если вы только начинаете работать с Terraform или просто пробуете Terraform с Firebase.
    • Вариант 2. Включите его в отдельный файл .tf (например, файл provider.tf ), отдельно от файла .tf , в котором вы указываете создаваемую инфраструктуру (например, файл main.tf ).

      • Используйте этот вариант, если вы являетесь частью большой команды, которой необходимо стандартизировать настройку.
      • При запуске команд Terraform файл provider.tf и файл main.tf должны находиться в одном каталоге.

  2. Включите следующую настройку provider в начало файла main.tf

    Вам необходимо использовать поставщика google-beta , поскольку это бета-версия использования Firebase с Terraform. Соблюдайте осторожность при использовании в производстве.

    # Terraform configuration to set up providers by version.
    terraform {
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 5.0"
        }
      }
    }
    
    # Configures the provider to use the resource block's specified project for quota checks.
    provider "google-beta" {
      user_project_override = true
    }
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    # This provider should only be used during project creation and initializing services.
    provider "google-beta" {
      alias = "no_user_project_override"
      user_project_override = false
    }

    Узнайте больше о различных типах атрибутов, связанных с проектом (включая то, что в этом руководстве называется «проектом проверки квоты») при использовании Terraform с Firebase.

  3. Перейдите к следующему разделу, чтобы завершить создание файла конфигурации и указать, какую инфраструктуру нужно создать.

Укажите, какую инфраструктуру создавать с использованием блоков resource

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

  1. Откройте файл main.tf

  2. В настройках provider включите следующую конфигурацию блоков resource .

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

    # Terraform configuration to set up providers by version.
    ...
    
    # Configures the provider to use the resource block's specified project for quota checks.
    ...
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    ...
    
    # Creates a new Google Cloud project.
    resource "google_project" "default" {
      provider   = google-beta.no_user_project_override
    
      name       = "Project Display Name"
      project_id = "project-id-for-new-project"
      # Required for any service that requires the Blaze pricing plan
      # (like Firebase Authentication with GCIP)
      billing_account = "000000-000000-000000"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    # Enables required APIs.
    resource "google_project_service" "default" {
      provider = google-beta.no_user_project_override
      project  = google_project.default.project_id
      for_each = toset([
        "cloudbilling.googleapis.com",
        "cloudresourcemanager.googleapis.com",
        "firebase.googleapis.com",
        # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
        "serviceusage.googleapis.com",
      ])
      service = each.key
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enables Firebase services for the new project created above.
    resource "google_firebase_project" "default" {
      provider = google-beta
      project  = google_project.default.project_id
    
      # Waits for the required APIs to be enabled.
      depends_on = [
        google_project_service.default
      ]
    }
    
    # Creates a Firebase Android App in the new project created above.
    resource "google_firebase_android_app" "default" {
      provider = google-beta
    
      project      = google_project.default.project_id
      display_name = "My Awesome Android app"
      package_name = "awesome.package.name"
    
      # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
      depends_on = [
        google_firebase_project.default,
      ]
    }

Если вы не знакомы с инфраструктурой проектов и приложений как ресурсов, просмотрите следующую документацию:

# Terraform configuration to set up providers by version.
...

# Configures the provider to use the resource block's specified project for quota checks.
...

# Configures the provider to not use the resource block's specified project for quota checks.
...

# Creates a new Google Cloud project.
resource "google_project" "default" {
  # Use the provider that enables the setup of quota checks for a new project
  provider   = google-beta.no_user_project_override

  name            = "Project Display Name"        // learn more about the project name
  project_id      = "project-id-for-new-project"  // learn more about the project ID
  # Required for any service that requires the Blaze pricing plan
  # (like Firebase Authentication with GCIP)
  billing_account = "000000-000000-000000"

  # Required for the project to display in any list of Firebase projects.
  labels = {
    "firebase" = "enabled"  // learn more about the Firebase-enabled label
  }
}

# Enables required APIs.
resource "google_project_service" "default" {
  # Use the provider without quota checks for enabling APIS
  provider = google-beta.no_user_project_override
  project  = google_project.default.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
# This action essentially "creates a Firebase project" and allows the project to use
# Firebase services (like Firebase Authentication) and
# Firebase tooling (like the Firebase console).
# Learn more about the relationship between Firebase projects and Google Cloud.
resource "google_firebase_project" "default" {
  # Use the provider that performs quota checks from now on
  provider = google-beta

  project  = google_project.default.project_id

  # Waits for the required APIs to be enabled.
  depends_on = [
    google_project_service.default
  ]
}

# Creates a Firebase Android App in the new project created above.
# Learn more about the relationship between Firebase Apps and Firebase projects.
resource "google_firebase_android_app" "default" {
  provider = google-beta

  project      = google_project.default.project_id
  display_name = "My Awesome Android app"  # learn more about an app's display name
  package_name = "awesome.package.name"    # learn more about an app's package name

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.default,
  ]
}


Шаг 2. Запустите команды Terraform для создания указанной инфраструктуры.

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

  1. Если вы впервые запускаете команды Terraform в каталоге, вам необходимо инициализировать каталог конфигурации и установить поставщика Google Terraform. Сделайте это, выполнив следующую команду:

    terraform init
  2. Создайте инфраструктуру, указанную в файле main.tf , выполнив следующую команду:

    terraform apply
  3. Убедитесь, что все было подготовлено или включено, как ожидалось:

    • Вариант 1. Посмотрите конфигурацию, напечатанную на вашем терминале, выполнив следующую команду:

      terraform show
    • Вариант 2. Просмотрите проект Firebase в консоли Firebase .



Ресурсы Firebase с поддержкой Terraform

Следующие ресурсы Firebase и Google поддерживают Terraform. И мы постоянно добавляем больше ресурсов! Поэтому, если вы не видите ресурс, которым хотите управлять с помощью Terraform, зайдите позже, чтобы узнать, доступен ли он, или запросите его , зарегистрировав проблему в репозитории GitHub .


Управление проектами и приложениями Firebase

  • google_firebase_project — включить службы Firebase в существующем проекте Google Cloud

  • Приложения Firebase

    • google_firebase_apple_app — создание приложения Firebase для платформы Apple или управление им.
    • google_firebase_android_app — создание приложения Firebase для Android или управление им.
    • google_firebase_web_app — создание веб-приложения Firebase или управление им.

Firebase Authentication

  • google_identity_platform_config — включите Google Cloud Identity Platform (GCIP) (которая является серверной частью Firebase Authentication ) и укажите настройки аутентификации на уровне проекта.

    • Для настройки Firebase Authentication через Terraform необходимо включить GCIP. Обязательно просмотрите образец файла .tf , чтобы узнать, как настроить Firebase Authentication .

    • Проект, в котором Terraform будет включать GCIP и/или Firebase Authentication должен находиться в тарифном плане Blaze (то есть проект должен иметь связанную учетную запись Cloud Billing ). Вы можете сделать это программно, установив атрибут billing_account в ресурсе google_project .

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

  • google_identity_platform_default_supported_idp_config — настройка распространенных федеративных поставщиков удостоверений, таких как Google, Facebook или Apple.

  • identity_platform_oauth_idp_config — настройка произвольных источников поставщика удостоверений OAuth (IdP).

  • google_identity_platform_inbound_saml_config — настройка интеграции SAML

Еще не поддерживается:

  • Настройка многофакторной аутентификации (MFA) через Terraform

Firebase Data Connect


Firebase Realtime Database

Еще не поддерживается:

  • Развертывание Firebase Realtime Database Security Rules через Terraform (узнайте, как развернуть эти Rules с помощью других инструментов, включая программные варианты)

Cloud Firestore

  • google_firestore_database — создать экземпляр Cloud Firestore

  • google_firestore_index — включить эффективные запросы для Cloud Firestore

  • google_firestore_document — заполнить экземпляр Cloud Firestore определенным документом в коллекции.

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


Cloud Storage for Firebase

  • google_firebase_storage_bucket — сделать существующую корзину Cloud Storage доступной для Firebase SDK, аутентификации и Firebase Security Rules

  • google_storage_bucket_object — добавить объект в корзину Cloud Storage

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


Firebase Security Rules (для Cloud Firestore и Cloud Storage )

Обратите внимание, что Firebase Realtime Database использует другую систему обеспечения для своих Firebase Security Rules .

  • google_firebaserules_ruleset — определяет Firebase Security Rules , которые применяются к экземпляру Cloud Firestore или сегменту Cloud Storage

  • google_firebaserules_release — развертывание определенных наборов правил в экземпляре Cloud Firestore или в сегменте Cloud Storage


Firebase App Check


Firebase Extensions



Примеры файлов конфигурации Terraform для распространенных случаев использования

Эта конфигурация создает новый проект Google Cloud , связывает проект с учетной записью Cloud Billing (для Firebase Authentication с GCIP требуется тарифный план Blaze), включает службы Firebase для проекта, настраивает Firebase Authentication с GCIP и регистрирует три разных типа приложений в проекте.

Обратите внимание, что включение GCIP необходимо для настройки Firebase Authentication через Terraform.

# Creates a new Google Cloud project.
resource "google_project" "auth" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for Firebase Authentication with GCIP).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "auth" {
  provider = google-beta.no_user_project_override
  project  = google_project.auth.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "identitytoolkit.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  depends_on = [
    google_project_service.auth,
  ]
}

# Creates an Identity Platform config.
# Also enables Firebase Authentication with Identity Platform in the project if not.
resource "google_identity_platform_config" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  # Auto-deletes anonymous users
  autodelete_anonymous_users = true

  # Configures local sign-in methods, like anonymous, email/password, and phone authentication.
  sign_in {
    allow_duplicate_emails = true

    anonymous {
      enabled = true
    }

    email {
      enabled = true
      password_required = false
    }

    phone_number {
      enabled = true
      test_phone_numbers = {
        "+11231231234" = "000000"
      }
    }
  }

  # Sets an SMS region policy.
  sms_region_config {
    allowlist_only {
      allowed_regions = [
        "US",
        "CA",
      ]
    }
  }

  # Configures blocking functions.
  blocking_functions {
    triggers {
      event_type = "beforeSignIn"
      function_uri = "https://us-east1-${google_project.auth.project_id}.cloudfunctions.net/before-sign-in"
    }
    forward_inbound_credentials {
      refresh_token = true
      access_token = true
      id_token = true
    }
  }

  # Configures a temporary quota for new signups for anonymous, email/password, and phone number.
  quota {
    sign_up_quota_config {
      quota = 1000
      start_time = ""
      quota_duration = "7200s"
    }
  }

  # Configures authorized domains.
  authorized_domains = [
    "localhost",
    "${google_project.auth.project_id}.firebaseapp.com",
    "${google_project.auth.project_id}.web.app",
  ]

  # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
  depends_on = [
    google_project_service.auth,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

Эта конфигурация создает новый проект Google Cloud , включает службы Firebase для проекта и предоставляет службу Data Connect .

# Creates a new Google Cloud project.
resource "google_project" "dataconnect" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required to use Firebase Data Connect).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "services" {
  provider = google-beta.no_user_project_override
  project  = google_project.dataconnect.project_id
  for_each = toset([
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedataconnect.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created earlier.
resource "google_firebase_project" "dataconnect" {
  provider = google-beta
  project  = google_project.dataconnect.project_id

  depends_on = [google_project_service.services]
}

# Create a Firebase Data Connect service
resource "google_firebase_data_connect_service" "dataconnect-default" {
  project         = google_firebase_project.dataconnect.project
  location        = "name-of-region-for-service"
  service_id      = "${google_firebase_project.dataconnect.project}-default-fdc"
  deletion_policy = "DEFAULT"
}

Эта конфигурация создает новый проект Google Cloud , включает службы Firebase для проекта, подготавливает экземпляр Realtime Database по умолчанию и регистрирует в проекте три разных типа приложений.

# Creates a new Google Cloud project.
resource "google_project" "rtdb" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb.project_id
  for_each = toset([
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb" {
  provider = google-beta
  project  = google_project.rtdb.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database" {
  provider    = google-beta
  project     = google_project.rtdb.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

Эта конфигурация создает новый проект Google Cloud , связывает проект с учетной записью Cloud Billing (для нескольких экземпляров Realtime Database требуется тарифный план Blaze), включает службы Firebase для проекта, подготавливает несколько экземпляров Realtime Database (включая экземпляр Realtime Database проекта по умолчанию) и регистрирует в проекте три разных типа приложений.

# Creates a new Google Cloud project.
resource "google_project" "rtdb-multi" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associate the project with a Cloud Billing account
  # (required for multiple Realtime Database instances).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb-multi" {
  provider = google-beta
  project  = google_project.rtdb-multi.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database-default" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb-multi.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Provisions an additional Realtime Database instance.
resource "google_firebase_database_instance" "database-additional" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/projects/locations#rtdb-locations
  # This location doesn't need to be the same as the default database instance.
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "name-of-additional-database-instance"
  type        = "USER_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

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

Он также предоставляет Firebase Security Rules для экземпляра Cloud Firestore по умолчанию, создает индекс Cloud Firestore и добавляет документ Cloud Firestore с исходными данными.

# Creates a new Google Cloud project.
resource "google_project" "firestore" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "firestore" {
  provider = google-beta.no_user_project_override
  project  = google_project.firestore.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "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
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "firestore" {
  provider                    = google-beta
  project                     = google_project.firestore.project_id
  name                        = "(default)"
  # See available locations: https://firebase.google.com/docs/firestore/locations
  location_id                 = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type                        = "FIRESTORE_NATIVE"
  concurrency_mode            = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a ruleset of Firestore Security Rules from a local file.
resource "google_firebaserules_ruleset" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
  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.firestore,
  ]
}

# Releases 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_project.firestore.project_id

  # Wait for Firestore to be provisioned before releasing the ruleset.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore index.
resource "google_firestore_index" "indexes" {
  provider = google-beta
  project  = google_project.firestore.project_id

  collection  = "quiz"
  query_scope = "COLLECTION"

  fields {
    field_path = "question"
    order      = "ASCENDING"
  }

  fields {
    field_path = "answer"
    order      = "ASCENDING"
  }

  # Wait for Firestore to be provisioned before adding this index.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore document with seed data.
# Don't use real end-user or production data in this seed document.
resource "google_firestore_document" "doc" {
  provider    = google-beta
  project     = google_project.firestore.project_id
  collection  = "quiz"
  document_id = "question-1"
  fields      = "{\"question\":{\"stringValue\":\"Favorite Database\"},\"answer\":{\"stringValue\":\"Firestore\"}}"

  # Wait for Firestore to be provisioned before adding this document.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

Это набор Cloud Firestore Security Rules , который должен находиться в локальном файле с именем firestore.rules .

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, create, update: if request.auth != null;
    }
  }
}

Эта конфигурация создает новый проект Google Cloud , связывает проект с Cloud Billing (для дополнительных сегментов требуется тарифный план Blaze), включает службы Firebase для проекта, предоставляет дополнительные сегменты Cloud Storage , отличные от стандартных, и регистрирует три разных типа приложений в проекте.

Он также предоставляет Firebase Security Rules для каждого сегмента Cloud Storage и загружает файл в один из сегментов Cloud Storage .

# Creates a new Google Cloud project.
resource "google_project" "storage-multi" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for multiple Cloud Storage buckets).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "storage-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.storage-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebaserules.googleapis.com",
    "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
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
}

# Provisions a Cloud Storage bucket.
resource "google_storage_bucket" "bucket-1" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  location = "name-of-region-for-bucket"
}

# Provisions an additional Cloud Storage bucket.
resource "google_storage_bucket" "bucket-2" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-additional-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  # This location does not need to be the same as the existing Storage bucket.
  location = "name-of-region-for-additional-bucket"
}

# Makes the first Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-1" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-1.name
}

# Makes the additional Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-2" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-2.name
}

# Creates a ruleset of Firebase Security Rules from a local file.
resource "google_firebaserules_ruleset" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  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 Storage buckets to be provisioned before creating this ruleset.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Releases the ruleset to the first Storage bucket.
resource "google_firebaserules_release" "bucket-1" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-1.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Releases the ruleset to the additional Storage bucket.
resource "google_firebaserules_release" "bucket-2" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-2.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Uploads a new file to the first Storage bucket.
# Do not use real end-user or production data in this file.
resource "google_storage_bucket_object" "cat-picture-multi" {
  provider = google-beta
  name     = "cat.png"
  source   = "path/to/cat.png"
  bucket   = google_storage_bucket.bucket-1.name
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Web app"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

Это набор Cloud Storage Security Rules , который должен находиться в локальном файле с именем storage.rules .

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /some_folder/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

Эта конфигурация создает новый проект Google Cloud , включает службы Firebase для проекта, а также настраивает и включает Firebase App Check для Cloud Firestore , чтобы доступ к нему можно было получить только из вашего приложения Android.

# Creates a new Google Cloud project.
resource "google_project" "appcheck" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "services" {
  provider = google-beta.no_user_project_override
  project  = google_project.appcheck.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    "firebaseappcheck.googleapis.com",
    "firestore.googleapis.com",
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created earlier.
resource "google_firebase_project" "appcheck" {
  provider = google-beta
  project  = google_project.appcheck.project_id

  depends_on = [google_project_service.services]
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "database" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  name     = "(default)"
  # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
  location_id = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type             = "FIRESTORE_NATIVE"
  concurrency_mode = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.appcheck,
  ]
}

# Creates a Firebase Android App in the new project created earlier.
resource "google_firebase_android_app" "appcheck" {
  provider     = google-beta
  project      = google_firebase_project.appcheck.project
  display_name = "Play Integrity app"
  package_name = "package.name.playintegrity"
  sha256_hashes = [
    # TODO: insert your Android app's SHA256 certificate
  ]
}

# It takes a while for App Check to recognize the new app
# If your app already exists, you don't have to wait 30 seconds.
resource "time_sleep" "wait_30s" {
  depends_on      = [google_firebase_android_app.appcheck]
  create_duration = "30s"
}

# Register the Android app with the Play Integrity provider
resource "google_firebase_app_check_play_integrity_config" "appcheck" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  app_id   = google_firebase_android_app.appcheck.app_id

  depends_on = [time_sleep.wait_30s, google_firestore_database.database]

  lifecycle {
    precondition {
      condition     = length(google_firebase_android_app.appcheck.sha256_hashes) > 0
      error_message = "Provide a SHA-256 certificate on the Android App to use App Check"
    }
  }
}

# Enable enforcement of App Check for Firestore
resource "google_firebase_app_check_service_config" "firestore" {
  provider = google-beta

  project    = google_firebase_project.appcheck.project
  service_id = "firestore.googleapis.com"

  depends_on = [google_project_service.services]
}

Эта конфигурация создает новый проект Google Cloud , включает службы Firebase для проекта и устанавливает в проект новый экземпляр Firebase Extension . Если экземпляр уже существует, его параметры обновляются на основе значений, указанных в конфиге.

# Creates a new Google Cloud project.
resource "google_project" "extensions" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required to use Firebase Extensions).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "extensions" {
  provider = google-beta.no_user_project_override
  project  = google_project.extensions.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "firebase.googleapis.com",
    "firebaseextensions.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "extensions" {
  provider = google-beta
  project  = google_project.extensions.project_id

  depends_on = [
    google_project_service.extensions,
  ]
}

# Installs an instance of the "Translate Text in Firestore" extension.
# Or updates the extension if the specified instance already exists.
resource "google_firebase_extensions_instance" "translation" {
  provider = google-beta
  project = google_project.extensions.project_id

  instance_id = "translate-text-in-firestore"
  config {
    extension_ref = "firebase/firestore-translate-text"

    params = {
      COLLECTION_PATH      = "posts/comments/translations"
      DO_BACKFILL          = true
      LANGUAGES            = "ar,en,es,de,fr"
      INPUT_FIELD_NAME     = "input"
      LANGUAGES_FIELD_NAME = "languages"
      OUTPUT_FIELD_NAME    = "translated"
    }

    system_params = {
      "firebaseextensions.v1beta.function/location"                   = "us-central1"
      "firebaseextensions.v1beta.function/memory"                     = "256"
      "firebaseextensions.v1beta.function/minInstances"               = "0"
      "firebaseextensions.v1beta.function/vpcConnectorEgressSettings" = "VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED"
    }
  }
}



Устранение неполадок и часто задаваемые вопросы

В этом руководстве при работе с «проектами» используются следующие атрибуты Terraform.

project в блоке resource

Рекомендуется: по возможности включать атрибут project в каждый блок resource

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

См. официальную документацию Terraform о project .

user_project_override в блоке provider

Для предоставления большинства ресурсов вам следует использовать user_project_override = true , что означает проверку квоты на соответствие вашему собственному проекту Firebase. Однако чтобы настроить новый проект так, чтобы он мог принимать проверки квот, сначала необходимо использовать user_project_override = false .

См. официальную документацию Terraform о user_project_override .

Убедитесь, что учетная запись пользователя, которую вы используете для запуска команд gcloud CLI приняла Условия обслуживания Firebase (Firebase ToS).

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

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

Подождите несколько минут, а затем попробуйте снова запустить terraform apply .

Это может быть связано с задержкой распространения в различных системах. Попробуйте решить эту проблему, импортировав ресурс в состояние Terraform, запустив terraform import . Затем попробуйте снова запустить terraform apply .

О том, как импортировать каждый ресурс, можно узнать в разделе «Импорт» его документации Terraform (например, документации «Импорт» для Cloud Firestore ).

Как следует из ошибки, Terraform, возможно, пытается предоставить несколько индексов и/или создать документ одновременно и столкнулся с ошибкой параллелизма. Попробуйте запустить terraform apply еще раз.

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

  • Убедитесь, что вы указали значение атрибута project .
  • Убедитесь, что вы используете поставщика с user_project_override = true (без псевдонима), который в примерах Firebase — google-beta .

Вот возможные причины, по которым идентификатор проекта может уже существовать:

  • Проект, связанный с этим идентификатором, принадлежит кому-то другому.

    • Решение: выберите другой идентификатор проекта.
  • Проект, связанный с этим идентификатором, был недавно удален (в состоянии обратимого удаления).

    • Решение: если вы считаете, что проект, связанный с идентификатором, принадлежит вам, проверьте состояние проекта с помощью REST API projects.get .
  • Проект, связанный с этим идентификатором, правильно существует под текущим пользователем. Возможная причина ошибки может заключаться в том, что предыдущее terraform apply было прервано.

    • Решение: выполните следующие команды:
      terraform import google_project.default PROJECT_ID а потом
      terraform import google_firebase_project.default PROJECT_ID

Если вы подготовили корзину Cloud Storage по умолчанию (через google_app_engine_application ) до того, как попытаетесь подготовить экземпляр Cloud Firestore по умолчанию, вы обнаружите, что ваш экземпляр Cloud Firestore по умолчанию уже подготовлен. Обратите внимание, что подготовленный экземпляр базы данных находится в режиме хранилища данных, а это означает, что он недоступен для Firebase SDK, аутентификации или Firebase Security Rules . Если вы хотите использовать Cloud Firestore с этими сервисами Firebase, вам необходимо очистить базу данных, а затем изменить ее тип базы данных в консоли Google Cloud .

Когда вы подготавливаете корзину Cloud Storage по умолчанию для проекта (через google_app_engine_application ), а у проекта еще нет экземпляра Cloud Firestore по умолчанию, google_app_engine_application автоматически подготавливает экземпляр Cloud Firestore по умолчанию для проекта.

Итак, поскольку экземпляр Cloud Firestore по умолчанию для вашего проекта уже подготовлен, google_firestore_database выдаст ошибку, если вы попытаетесь снова явно предоставить этот экземпляр по умолчанию.

После того как экземпляр Cloud Firestore по умолчанию для проекта будет подготовлен, вы не сможете «повторно подготовить» его или изменить его местоположение. Обратите внимание, что подготовленный экземпляр базы данных находится в режиме хранилища данных, а это означает, что он недоступен для Firebase SDK, аутентификации или Firebase Security Rules . Если вы хотите использовать Cloud Firestore с этими сервисами Firebase, вам необходимо очистить базу данных, а затем изменить ее тип базы данных в консоли Google Cloud .