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

1. مقدمة

الأهداف

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

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

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

أهداف الدورة التعليمية

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

المتطلبات

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

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

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

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

2. الحصول على الرمز الأولي

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

استنسِخ مستودع GitHub الخاص بالبرنامج التعليمي من سطر الأوامر:

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

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

3- إنشاء إعداد Terraform

إعداد Terraform

  1. في قاعدة الرموز البرمجية لتطبيق العيّنة الذي تم تنزيله، انتقِل إلى جذر الدليل web.
  2. في جذر هذا الدليل، أنشِئ ملف إعداد Terraform باسم main.tf يتضمّن الإعداد الأوّلي التالي:

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

يحتوي كل موفّر من google-beta على سمة باسم user_project_override تحدّد طريقة التحقّق من الحصة من Terraform. لتوفير معظم الموارد، عليك استخدام user_project_override = true، ما يعني التحقّق من الحصة المتاحة في مشروعك على Firebase. ومع ذلك، لإعداد مشروعك الجديد كي يتمكّن من قبول عمليات التحقّق من الحصة، عليك أولاً استخدام user_project_override=false. تتيح لك بنية alias في Terraform التمييز بين إعدادَي موفّر الخدمة في الخطوات التالية من هذا الدرس العملي.

إعداد Terraform في الدليل

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

لتنفيذ عملية التهيئة هذه، نفِّذ الأمر التالي من جذر الدليل نفسه الذي يحتوي على ملف الإعداد main.tf:

terraform init

4. إنشاء مشروع Firebase باستخدام Terraform

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

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

  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 (أسفل الحزمة التي تنشئ مشروعًا جديدًا على Cloud مباشرةً)، أضِف حزمة الموارد التالية:

    main.tf
    ...
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "serviceusage" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "firebase" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    من خلال تفعيل Service Usage API، سيتمكّن مشروعك الجديد من قبول عمليات التحقّق من الحصة. لذلك، عند توفير الموارد وتفعيل الخدمات في كل مرة لاحقة، عليك استخدام مقدّم الخدمة مع user_project_override (بدون الحاجة إلى اسم مستعار).

إضافة رمز برمجي لتفعيل خدمات Firebase

آخر خطوة مطلوبة "لإنشاء مشروع على Firebase" هي تفعيل خدمات Firebase في المشروع.

في ملف إعداد main.tf، أضِف كتلة الموارد التالية.

كما ذكرنا أعلاه، يُرجى العِلم أنّ حزمة الموارد هذه تستخدم موفّر user_project_override (لا حاجة إلى اسم مستعار).

main.tf

...

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

  project = google_project.default.project_id

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

في قسم الموارد أعلاه، قد تلاحظ العبارة depends_on، التي تطلب من Terraform الانتظار إلى أن يتم تفعيل واجهات برمجة التطبيقات الأساسية. بدون هذه العبارة، لن يعرف 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.

مشروع FriendlyChat Codelab من Terraform الذي تم اختياره في &quot;وحدة تحكّم Firebase&quot;

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 Authentication وإعداد طريقة تسجيل الدخول باستخدام Google.

يُرجى العِلم أنّه في هذا الدرس العملي، نوفّر خيارَين مختلفَين لإعداد خدمة "المصادقة عبر Firebase":

  • الخيار 1 (يُنصح به): إعداد خدمة Firebase Authentication في وحدة التحكّم، وهو لا يتطلّب GCIP.
    • يعني استخدام هذا الخيار أنّه لا عليك ربط مشروعك الجديد بحساب فوترة على Cloud.
  • الخيار 2: إعداد Firebase Authentication من خلال Terraform باستخدام واجهات برمجة التطبيقات في Google Cloud Identity Platform (GCIP)
    • يعني استخدام هذا الخيار أنّه عليك ربط مشروعك الجديد بحساب فوترة في Cloud، لأنّ GCIP يتطلّب أن يكون المشروع ضمن خطة أسعار Blaze.

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

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

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

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

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

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

تفعيل الفوترة من خلال Terraform

  1. إذا لم يكن لديك حساب فوترة في Cloud، فإنّ الخطوة الأولى هي إنشاء حساب جديد في وحدة تحكّم Google Cloud. عند إجراء ذلك، دوِّن رقم تعريف حساب الفوترة. يمكن العثور على معرّف حساب الفوترة في صفحة الفوترة ضِمن معرّف حساب الفوترة المرتبط بمشروعك.تفعيل حساب فوترة باستخدام &quot;وحدة تحكّم Google Cloud&quot;
  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 Console
  4. يمكنك إعداد عميل OAuth في صفحة بيانات الاعتماد باتّباع الخطوات التالية:
    1. انقر على إنشاء بيانات اعتماد واختَر معرِّف عميل OAuth.
    2. من القائمة المنسدلة نوع التطبيق، اختَر تطبيق الويب.
    3. في حقل الاسم، أدخِل اسم تطبيقك، مثل FriendlyChat (ليس من الضروري أن يكون هذا الاسم فريدًا على مستوى العالم).
    4. اسمح لعنوان URL الخاص بتطبيقك باستخدام عميل OAuth هذا من خلال ضبط ما يلي:
      • ضمن مصادر JavaScript المسموح بها، انقر على إضافة معرّف الموارد المنتظم (URI) وأدخِل
        https://<PROJECT_ID>.firebaseapp.com، حيث <PROJECT_ID> هو رقم تعريف المشروع الذي ضبطته في main.tf.
      • ضمن معرّفات الموارد المنتظمة (URI) المعتمَدة لإعادة التوجيه، انقر على إضافة معرّف الموارد المنتظمة (URI) وأدخِل
        https://<PROJECT_ID>.firebaseapp.com/__/auth/handler، حيث يمثّل <PROJECT_ID> رقم تعريف المشروع الذي ضبطته في main.tf.
    5. انقر على حفظ.
    الحصول على معرّف عميل OAuth2 وسرّه من صفحة &quot;بيانات الاعتماد&quot; في Google Cloud Console
  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 كموفّر خدمة تسجيل دخول مفعّل.صفحة &quot;المصادقة&quot; في وحدة تحكّم Firebase: ميزة &quot;تسجيل الدخول باستخدام حساب Google&quot; مفعَّلة

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 Functions. بالنسبة إلى هذا الدرس العملي، يمكنك استخدام us-east1 (كارولينا الجنوبية) أو استخدام المنطقة الأقرب إليك (راجِع مواقع Cloud Firestore).
  3. يجب حماية كل مثيل لقاعدة بيانات Firestore يمكن الوصول إليه من خلال Firebase باستخدام قواعد أمان Firebase.

    يوفّر الرمز النموذجي في هذا الدرس العملي مجموعة من قواعد Firestore الآمنة في الملف firestore.rules، ويمكنك العثور عليه في جذر الدليل web.
  4. أضِف إلى ملف main.tf كتل الموارد التالية لإجراء ما يلي:
    • أنشئ مجموعة قواعد من "قواعد أمان Firebase" من ملف firestore.rules المحلي.
    • أصدِر مجموعة القواعد لمثيل Firestore.
    يُرجى العِلم أنّ كتل الموارد هذه تؤدي وظيفة مماثلة للنقر على الزر نشر في وحدة تحكّم Firebase أو تنفيذ firebase deploy --only firestore:rules.

    main.tf
    ...
    
    # Create a ruleset of Firestore Security Rules from a local file.
    resource "google_firebaserules_ruleset" "firestore" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      source {
        files {
          name = "firestore.rules"
          # Write security rules in a local file named "firestore.rules".
          # Learn more: https://firebase.google.com/docs/firestore/security/get-started
          content = file("firestore.rules")
        }
      }
    
      # Wait for Firestore to be provisioned before creating this ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    }
    
    # Release the ruleset for the Firestore instance.
    resource "google_firebaserules_release" "firestore" {
      provider     = google-beta
    
      name         = "cloud.firestore"  # must be cloud.firestore
      ruleset_name = google_firebaserules_ruleset.firestore.name
      project      = google_firebase_project.default.project
    
      # Wait for Firestore to be provisioned before releasing the ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    
      lifecycle {
        replace_triggered_by = [
          google_firebaserules_ruleset.firestore
        ]
      }
    }
    
  5. نفِّذ الأمر terraform apply لتوفير قاعدة بيانات Firestore ونشر قواعد الأمان الخاصة بها.
  6. تأكَّد من توفير قاعدة البيانات ونشر قواعد الأمان الخاصة بها:
    1. في وحدة تحكّم Firebase، ابحث عن قسم إنشاء في اللوحة اليمنى.
    2. انتقِل إلى قسم قاعدة بيانات Firestore، ثم انقر على علامة التبويب القواعد.
    التحقّق من قواعد Cloud Firestore باستخدام وحدة تحكّم Firebase

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. انتقِل إلى قسم سعة التخزين، ثم انقر على علامة التبويب القواعد.
    التحقّق من قواعد الأمان باستخدام وحدة تحكّم Firebase

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

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

  1. افتح نافذة محطة طرفية جديدة، ونفِّذ أمر Firebase CLI التالي من الدليل web لبدء المحاكي:
    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 وبدء عملية إنشاء حزمة webpack

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

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

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

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

عليك أيضًا إضافة إعدادات Firebase إلى تطبيقك لكي تعرف حِزم تطوير البرامج (SDK) لبرنامج 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 لإدارة موارد السحابة الإلكترونية
  • استخدام Terraform لإعداد منتجات Firebase (المصادقة وFirestore وCloud Storage وقواعد الأمان)
  • تشغيل تطبيق ويب واختباره محليًا باستخدام "مجموعة أدوات المحاكاة المحلية" من Firebase
  • استيراد Firebase إلى تطبيق ويب
  • استخدام Terraform لتكرار إعدادات في بيئات متعددة

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