إعداد وإدارة مشاريع ومنتجات Firebase من خلال Terraform

1- مقدمة

الأهداف

يمكنك استخدام Terraform لإعداد مشروع Firebase وإدارته، بما في ذلك الضبط الآلي لمنتجات البنية الأساسية ومنتجات Firebase.

يشرح هذا الدرس التطبيقي أولاً طريقة إنشاء ملف إعدادات Terraform لإنشاء مشروع جديد في Firebase، وتليه طريقة إعداد التطبيقات ومنتجات Firebase التي تريد استخدامها في هذا المشروع. كما نتناول أيضًا أساسيات سطر الأوامر Terraform، مثل معاينة التغييرات التي سيتم إجراؤها ثم تنفيذها.

إذا أردت التعرّف على كيفية إعداد وإدارة مشاريع ومنتجات Firebase باستخدام Terraform، يمكنك الاستفادة من هذا الدرس التطبيقي حول الترميز.

المعلومات التي ستطّلع عليها

  • كيفية إنشاء ملف إعداد Terraform (*.tf)
  • كيفية استخدام أوامر Terraform CLI لإدارة البنية الأساسية
  • كيفية تعديل الإعدادات لتعديل الموارد والخدمات
  • كيفية تطبيق الإعدادات على تطبيق ويب حقيقي (يُسمى المحادثة الودية)
  • كيفية تحديد تهيئات متوازية (ومتزامنة) في بيئات مختلفة (الإنتاج، والمراحل، وما إلى ذلك)

المتطلبات

لتحقيق النجاح في هذا الدرس التطبيقي حول الترميز، يجب أن تجيد استخدام لغة Terraform ومصطلحاتها، بما في ذلك المتطلّبات الأساسية التالية:

  • ثبِّت Terraform وتعرّف على Terraform باستخدام برامجه التعليمية الرسمية

يوفّر هذا الدرس التطبيقي حول الترميز نموذجًا فعليًا لتطبيق يتيح لك اختبار المحتوى الذي تقدّمه والتفاعل معه عبر Terraform. لإجراء ذلك، يجب توفر ما يلي:

  • رمز نموذجي لتطبيق ويب: يمكنك تنزيل هذا الرمز في الخطوة التالية من الدرس التطبيقي حول الترميز.
  • مدير الحزمة npm (الذي يأتي عادةً مع Node.js) - ثبِّت هذه الأدوات
  • واجهة سطر الأوامر في Firebase: تثبيت واجهة سطر الأوامر هذا وتسجيل الدخول

2- الحصول على رمز البدء

في هذا الدرس التطبيقي حول الترميز، يمكنك اختبار ما تقدّمه عبر تطبيق Terraform باستخدام تطبيق ويب حقيقي. نوصي بفعل ذلك حتى تفهم كل الخطوات اللازمة لاستخدام الموارد المقدمة من Terraform.

استنسِخ مستودع GitHub في الدرس التطبيقي حول الترميز من سطر الأوامر:

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

يمكنك بدلاً من ذلك تنزيل المستودع كملف ZIP إذا لم يكن git مثبّتًا لديك.

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. تسمح لك بنية Terraform alias بالتمييز بين إعدادَي الموفّر في الخطوات التالية من هذا الدرس التطبيقي حول الترميز.

تهيئة Terraform في الدليل

لإنشاء إعدادات جديدة للمرة الأولى، يجب تنزيل موفِّر الخدمة المحدَّد في الإعدادات.

لإجراء عملية الإعداد هذه، شغِّل الأمر التالي من جذر الدليل نفسه الذي يتضمّن ملف الإعداد main.tf:

terraform init

4. إنشاء مشروع على Firebase عبر Terraform

من أجل "إنشاء مشروع في Firebase"، من المهم تذكُّر أنّ كلّ مشروع في Firebase هو في الواقع مشروع على Google Cloud، ولكن مع تفعيل خدمات Firebase له.

إضافة وحدات لمشروع Google Cloud الأساسي وواجهات برمجة التطبيقات

  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. بعد ذلك، عليك تفعيل واجهات برمجة التطبيقات الأساسية المطلوبة: واجهة برمجة التطبيقات Service Usage API وFirebase Management 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
    }
    
    من خلال تفعيل واجهة برمجة التطبيقات لاستخدام الخدمة، سيتمكّن مشروعك الجديد من قبول عمليات التحقّق من الحصة. ولذلك، بالنسبة إلى جميع عمليات توفير الموارد وتفعيل الخدمات اللاحقة، عليك استخدام موفِّر الخدمة مع 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 الانتظار إلى أن يتم تفعيل واجهات برمجة التطبيقات الأساسية. بدون هذه العبارة، لن يعرف Terraform الاعتمادية وقد يواجه أخطاء عند توفير الموارد بالتوازي.

تطبيق الإعدادات

  1. لتوفير الموارد الجديدة وتفعيل واجهات برمجة التطبيقات المحدّدة في ملف الإعداد، شغِّل الأمر التالي من جذر الدليل نفسه كملف 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.

مشروع درس تطبيقي حول الترميز في Terraform FriendlyChat تم اختياره في وحدة تحكُّم Firebase

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.
  • الخيار 2: إعداد مصادقة Firebase عبر Terraform باستخدام واجهات برمجة تطبيقات Google Cloud Identity Platform (GCIP)
    • يعني استخدام هذا الخيار أنّه عليك ربط مشروعك الجديد بحساب فوترة Cloud لأنّ برنامج GCIP يتطلب أن يكون المشروع ضمن خطة أسعار Blaze.

الخيار 1: إعداد المصادقة باستخدام وحدة تحكُّم Firebase

لإعداد مصادقة Firebase باستخدام وحدة تحكُّم Firebase، ليس من الضروري أن يكون مشروعك ضمن خطة أسعار Blaze.

إليك كيفية إعداد مصادقة Firebase وتسجيل الدخول باستخدام حساب Google:

  1. في وحدة تحكُّم Firebase، ابحث عن قسم الإصدار في اللوحة اليمنى.
  2. انقر على المصادقة، ثم انقر على البدء، ثم انقر على علامة التبويب طريقة تسجيل الدخول (أو انقر هنا للانتقال إلى هناك مباشرةً).
  3. انقر على إضافة مقدّم خدمة جديد، ثم اختَر Google من القسم مقدّمو خدمات إضافيون.
  4. فعِّل الخيار تفعيل.
  5. اضبط الاسم الذي يظهر بشكل علني لتطبيقك على FriendlyChat (وليس من الضروري أن يكون الاسم فريدًا عالميًا).
  6. اختَر بريد إلكتروني لدعم المشروع من القائمة المنسدلة، ثم انقر على حفظ.إعداد مصادقة Firebase في &quot;وحدة تحكُّم Firebase&quot;
  7. ومن المفترض أن ترى Google كمقدّم خدمة تسجيل دخول مفعَّل.صفحة مصادقة وحدة تحكم Firebase: تم تفعيل تسجيل الدخول بحساب Google

الخيار 2: إعداد المصادقة عبر Terraform باستخدام واجهات برمجة تطبيقات Google Cloud Identity Platform (GCIP)

لإعداد مصادقة Firebase عبر Terraform، يجب استخدام واجهات برمجة تطبيقات GCIP API، مما يعني أن المشروع يجب أن يكون ضمن خطة تسعير Blaze. يمكنك ترقية مشروعك في Firebase لاستخدام خطة Blaze من خلال ربط حساب فوترة على Cloud بالمشروع.

تفعيل الفوترة عبر Terraform

  1. إذا لم يكن لديك حساب فوترة في Cloud من قبل، تتمثّل الخطوة الأولى في إنشاء حساب جديد في Google Cloud Console. عند القيام بذلك، دوِّن رقم تعريف حساب الفوترة. يمكن العثور على رقم تعريف حساب الفوترة في صفحة الفوترة في رقم تعريف حساب الفوترة المرتبط بمشروعك.تفعيل حساب فوترة باستخدام وحدة تحكُّم Google Cloud
  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. انتقل إلى واجهات برمجة التطبيقات الخدمات في Google Cloud Console لتنفيذ هذا الإعداد.
  3. بما أنّها المرة الأولى التي تنشئ فيها معرِّف عميل لهذا المشروع، عليك ضبط شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth.
    1. افتح شاشة موافقة OAuth، ثم اختَر المشروع الذي أنشأته للتو.
    2. اضبط نوع المستخدم على خارجي، ثمّ انقر على إنشاء.
    3. في الشاشة التالية، أكمِل الخطوات التالية، ثم انقر على حفظ ومتابعة.
      • يجب ضبط اسم التطبيق الذي يكون علنيًا لتطبيقك على FriendlyChat (وليس من الضروري أن يكون فريدًا عالميًا).
      • اختَر بريدًا إلكترونيًا لدعم المستخدمين من القائمة المنسدلة.
      • يُرجى إدخال عنوان بريد إلكتروني لمعلومات الاتصال بالمطوِّر.
    4. في الشاشات التالية، أكمل ما يلي:
      • وافِق على الإعدادات التلقائية في صفحة النطاقات، ثم انقر على حفظ ومتابعة.
      • اقبل الإعدادات التلقائية في صفحة المستخدمون التجريبيون، ثم انقر على حفظ ومتابعة.
      • راجِع الملخّص، ثم انقر على الرجوع إلى لوحة البيانات.
      إعداد عميل OAuth2 باستخدام وحدة تحكُّم Google Cloud
  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. انقر على حفظ.
    الحصول على معرّف وسر عميل OAuth2 من صفحة &quot;بيانات اعتماد Google Cloud Console&quot;
  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: تم تفعيل تسجيل الدخول بحساب Google

7- إعداد قاعدة بيانات Firestore وقواعد الأمان الخاصة بها

في تطبيق الويب الخاص بالدرس التطبيقي حول الترميز، ستتمكّن من تخزين الرسائل بين المستخدمين في قاعدة بيانات Firestore.

  1. لتفعيل واجهات برمجة التطبيقات المطلوبة وتوفير مثيل قاعدة البيانات، أضِف ملف 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. بالنسبة إلى هذا الدرس التطبيقي، يمكنك استخدام 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. انتقِل إلى قسم قاعدة بيانات متجر النار، ثم انقر على علامة التبويب القواعد.
    التحقّق من قواعد Cloud Firestore باستخدام &quot;وحدة تحكُّم Firebase&quot;

8- إعداد حزمة Cloud Storage وقواعد الأمان الخاصة بها

بالنسبة إلى تطبيق الويب الخاص بالدرس التطبيقي حول الترميز، سيكون بإمكانك تخزين الصور التي تمت مشاركتها بين المستخدمين في حزمة على Cloud Storage.

  1. لتفعيل واجهات برمجة التطبيقات المطلوبة وتوفير حزمتك التلقائية على 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. يجب حماية كل حزمة في Cloud Storage يمكن الوصول إليها من خلال 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. انتقِل إلى قسم مساحة التخزين، ثم انقر على علامة التبويب القواعد.
    التحقّق من قواعد الأمان باستخدام &quot;وحدة تحكُّم Firebase&quot;

9- تشغيل تطبيقك على الجهاز

أنت الآن جاهز لتشغيل تطبيق الويب للمرة الأولى. ستستخدم محاكي استضافة Firebase لعرض تطبيقك محليًا.

  1. افتح نافذة طرفية جديدة، ومن دليل web، شغِّل أمر Firebase CLI التالي لبدء المحاكي:
    firebase emulators:start --project=<PROJECT_ID>
    
  2. في المتصفّح، افتح تطبيق الويب على عنوان URL المحلي الذي يعرضه واجهة سطر الأوامر (يكون عادةً http://localhost:5000).

من المفترض أن تظهر لك واجهة المستخدم لتطبيق FriendlyChat التي لم تعمل (حتى الآن). لم يتم ربط التطبيق بمنصة Firebase بعد، ولكن من خلال إكمال الخطوات التالية في هذا الدرس التطبيقي حول الترميز.

تجدر الإشارة إلى أنّه كلما أجريت تغييرات على تطبيق الويب (كما تفعل في الخطوات التالية ضمن هذا الدرس التطبيقي حول الترميز)، احرص على إعادة تحميل المتصفّح لتعديل عنوان URL المحلي بهذه التغييرات.

10- تثبيت Firebase وإعداده وإعداده

لتشغيل تطبيق مع Firebase، يحتاج تطبيقك إلى حزمة تطوير البرامج (SDK) لمنصّة Firebase وإعداد Firebase لمشروعك في Firebase.

الرمز النموذجي لهذا الدرس التطبيقي حول الترميز هو تطبيق يعمل حاليًا مع جميع الاعتماديات والوظائف المطلوبة لاستخدام منتجات Firebase المختلفة في التطبيق. يمكنك الانتقال إلى web/package.json وweb/src/index.js للاطّلاع على ما تم إنجازه من قبل.

على الرغم من اكتمال نموذج الرمز في الغالب، لا يزال عليك تنفيذ بعض الإجراءات لتشغيل تطبيقك، بما في ذلك تثبيت حزمة تطوير البرامج (SDK) لمنصّة Firebase، وبدء الإصدار، وإضافة إعدادات Firebase إلى تطبيقك، وأخيرًا إعداد Firebase.

تثبيت حزمة تطوير البرامج (SDK) لمنصّة Firebase وبدء إنشاء حزمة الويب

وعليك تشغيل بعض الأوامر لبدء إنشاء تطبيقك.

  1. افتح نافذة طرفية جديدة.
  2. تأكَّد من أنّك في جذر الدليل web.
  3. شغِّل npm install لتنزيل حزمة تطوير البرامج (SDK) لمنصّة Firebase.
  4. يمكنك تشغيل npm update لتحديث أي تبعيات.
  5. يمكنك تشغيل npm run start لبدء تشغيل حِزمة الويب.

بالنسبة إلى بقية الدروس التطبيقية حول الترميز، ستعمل حزمة الويب الآن على إعادة إنشاء رمز المصدر باستمرار.

إضافة إعدادات Firebase إلى تطبيقك

عليك أيضًا إضافة إعدادات Firebase إلى تطبيقك حتى تعرِف حِزم SDK لمنصة Firebase مشروع Firebase الذي تريد أن تستخدمها.

بالنسبة إلى هذا الدرس التطبيقي حول الترميز، لديك خياران مختلفان لإعداد Firebase:

  • الخيار 1: احصل على تهيئة Firebase من وحدة تحكُّم Firebase.
  • الخيار 2: احصل على تهيئة Firebase عبر Terraform.

الخيار 1: الحصول على الإعدادات من وحدة تحكُّم Firebase وإضافتها إلى قاعدة الرموز

  1. في "وحدة تحكُّم Firebase"، انتقِل إلى إعدادات المشروع.
  2. انتقِل للأسفل وصولاً إلى بطاقة تطبيقاتك، ثم اختَر تطبيق الويب.
  3. اختَر الإعداد من جزء مقتطف حزمة تطوير البرامج (SDK) لمنصّة Firebase، ثمّ انسخ مقتطف الضبط.
  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 على أنه قيمة ناتج في واجهة سطر الأوامر.

  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 والسمة billing_account (في حال إعداد المصادقة عبر Terraform) باستخدام القيم الخاصة بك.
      • في مجموعة مصادر 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 والسمة billing_account (في حال إعداد المصادقة عبر Terraform) باستخدام القيم الخاصة بك.
      • في مجموعة مصادر 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"]
      
      ومع ذلك، يُعرف المشروع الحالي الذي أنشأته في الجزء الأول من هذا الدرس التطبيقي باسم Terraform كما يلي:
      google_project.default
      google_firebase_project.default
      google_firebase_android_app.default
      
    2. يمكنك تشغيل terraform plan لمعرفة الإجراءات التي ستتخذها Terraform نظرًا للحالة الحالية.

      من المفترض أن توضح النتائج أن Terraform سيحذف المشروع الذي أنشأته في الجزء الأول من هذا الدرس التطبيقي وينشئ مشروعين جديدين. ويرجع ذلك إلى أنّ 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 ستحذف المشروع الذي أنشأته في الجزء الأول من هذا الدرس التطبيقي.
  4. تشغيل "terraform apply" لإدارة "التقسيم المرحلي" الجديد مشروع Firebase وجميع موارده وتفعيل خدماته.
  5. تحقَّق من أنّه تمت إدارة جميع الخدمات وتفعيلها على النحو المتوقّع من خلال التحقّق منها في وحدة تحكُّم Firebase كما في السابق.

12- خطوة إضافية: نشر تطبيقات المرحلة والإنتاج

  1. في قاعدة رموز تطبيقك، عليك تغيير firebase-config.js لاستخدام إعدادات Firebase من مشروعك المرحلي بدلاً من ذلك.

    لتذكير نفسك بكيفية الحصول على إعداد Firebase وإضافته إلى تطبيقك، اطّلِع على الخطوة السابقة من هذا الدرس التطبيقي حول الترميز، وأضِف إعدادات Firebase إلى تطبيقك.
  2. في جذر دليل web، شغِّل الأمر التالي لنشر تطبيقك في مشروع Firebase المرحلي.
    firebase deploy --only hosting --project=<STAGING_PROJECT_ID>
    
  3. افتح تطبيق التقسيم في المتصفّح من خلال عنوان URL المطبوع في ناتج firebase deploy. جرِّب تسجيل الدخول وإرسال الرسائل وتحميل الصور.

    عند نشر تطبيق في مشروع Firebase، يستخدم موارد Firebase حقيقية، وليس موارد تمت محاكاتها. أثناء تفاعلك مع تطبيقك المرحلي، من المفترض أن تظهر البيانات والصور في المشروع المرحلي ضمن "وحدة تحكُّم Firebase".
  4. بعد اختبار تطبيقك في التقسيم المرحلي، يمكنك تغيير firebase-config.js مرة أخرى واستخدام إعداد Firebase لمشروع الإنتاج (المشروع الأول الذي أنشأته في هذا الدرس التطبيقي حول الترميز).
  5. في جذر دليل web، شغِّل الأمر التالي لنشر تطبيقك في مشروع Firebase للإنتاج.
    firebase deploy --only hosting --project=<PRODUCTION_PROJECT_ID>
    
  6. افتح تطبيق الإنتاج في المتصفّح من خلال عنوان URL المطبوع في ناتج firebase deploy. يمكنك محاولة تسجيل الدخول وإرسال الرسائل وتحميل الصور.

    من المفترَض أن تظهر لك البيانات والصور في مشروع الإنتاج في "وحدة تحكُّم Firebase".
  7. عند الانتهاء من التفاعل مع التطبيقَين في هذا الدرس التطبيقي حول الترميز، يمكنك منع Firebase من عرضهما. شغِّل الأمر التالي لكل مشروع من مشاريعك:
    firebase hosting:disable --project=<STAGING_PROJECT_ID>
    
    firebase hosting:disable --project=<PRODUCTION_PROJECT_ID>
    

13- تهانينا

لقد استخدمت Terraform لإعداد تطبيق ويب للدردشة في الوقت الفعلي! وقد اتّبعت أفضل الممارسات المتعلّقة ببيئات التطوير من خلال إنشاء مشاريع منفصلة في Firebase للتخطيط والإنتاج.

المواضيع التي تناولناها

  • استخدام Terraform CLI لإدارة موارد السحابة الإلكترونية
  • استخدام Terraform لضبط منتجات Firebase (المصادقة وFirestore وCloud Storage وقواعد الأمان)
  • تشغيل تطبيق ويب واختباره محليًا باستخدام "مجموعة أدوات المحاكاة المحلية من Firebase"
  • استيراد Firebase إلى تطبيق ويب
  • استخدام Terraform لتكرار تهيئة عبر بيئات متعددة

لمزيد من المعلومات حول Firebase وTeraform، يمكنك الاطّلاع على المستندات. يمكنك العثور على قائمة بجميع منتجات Firebase التي تدعم Terraform، وعيّنة من إعدادات Terraform لحالات الاستخدام الشائعة، بالإضافة إلى معلومات مفيدة لتحديد المشاكل وحلّها والأسئلة الشائعة.