دليل 101 حول Cloud Foundation

1. مقدمة حول CFT 101

b1d2ab0f35bb62a8.png

تاريخ آخر تعديل: 11-02-2022

ما هي Cloud Foundation Toolkit؟

في الأساس، توفّر CFT نماذج لأفضل الممارسات من أجل بدء استخدام Google Cloud Platform بسرعة. في هذا البرنامج التعليمي، ستتعرّف على كيفية المساهمة في Cloud Foundation Toolkit.

المتطلبات

  • حساب على GitHub
  • تثبيت Docker على جهازك أو استخدام Cloud Shell ( تثبيت على Mac، تثبيت على Windows)
  • أداة تعديل الرموز البرمجية (مثال: Visual Studio Code)
  • معرفة أساسية بـ Git وGitHub
  • بعض الخبرة في Terraform و"البنية الأساسية كرمز"
  • إذن منح دور "منشئ المشروع" إلى حساب خدمة
  • مؤسسة في Google Cloud ومجلد اختبار وحساب فوترة

ما ستنشئه

في هذا الدرس التطبيقي حول الترميز، ستتعلّم كيفية المساهمة في Cloud Foundation Toolkit (CFT).

عليك إجراء ما يلي:

  • إعداد بيئة تطوير للمساهمة في CFT
  • إضافة ميزة إلى وحدة CFT
  • إضافة اختبارات للميزة المضافة
  • تنفيذ اختبارات الدمج في CFT
  • تنفيذ اختبارات lint
  • إرسال الرمز البرمجي إلى GitHub وإرسال طلب سحب

ستنفّذ جميع الخطوات المذكورة أعلاه من خلال إضافة ميزة جديدة إلى وحدة CFT في Google Cloud Storage. ستضيف تصنيفًا باسم "silly_label"، وسيتم تلقائيًا إضافة هذا التصنيف إلى جميع الحِزم التي تم إنشاؤها من خلال وحدة GCS CFT. ستتمكّن أيضًا من كتابة اختبارات للتحقّق من صحة الميزة وضمان التكامل التام.

2. إعداد بيئة التطوير

يمكنك استخدام Cloud Shell لأغراض التطوير إذا أردت. إذا كنت لا تريد استخدام Cloud Shell للمساهمة في CFT، يمكنك إعداد بيئة التطوير على جهازك.

إعداد Git

يستند GitHub إلى نظام مفتوح المصدر للتحكّم في الإصدارات (VCS) يُعرف باسم Git. يتحمّل Git مسؤولية كل ما يحدث على جهازك أو Cloud Shell من أنشطة متعلقة بـ GitHub.

  1. عند استخدام Cloud Shell، لن تحتاج إلى تثبيت git لأنّه مثبَّت مسبقًا.
$ git --version
# This will display the git version on the Cloud Shell.

إذا كنت بصدد إعداد بيئة التطوير على جهازك، عليك تثبيت Git.

ضبط اسم المستخدم والبريد الإلكتروني في Git

يستخدم Git اسم مستخدم لربط عمليات الإيداع بهوية. اسم مستخدم Git ليس هو نفسه اسم مستخدم GitHub.

يمكنك تغيير الاسم المرتبط بعمليات الإضافة إلى Git باستخدام الأمر git config. لن يؤثر تغيير الاسم المرتبط بعمليات الإرسال في Git باستخدام git config إلا في عمليات الإرسال المستقبلية، ولن يغيّر الاسم المستخدَم في عمليات الإرسال السابقة.

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

3- مستودع GCS الخاص بأدوات Fork CFT

إنشاء نسخة طبق الأصل من مستودع CFT

لقد أعددت Git على جهازك أو Cloud Shell في الخطوة السابقة. عليك الآن إنشاء نسخة طبق الأصل من مستودع CFT في Google Cloud Storage لبدء المساهمة.

النسخة المتفرّعة هي نسخة من مستودع. يتيح لك إنشاء نسخة من مستودع تجربة التغييرات بحرية بدون التأثير في المشروع الأصلي.

في معظم الأحيان، تُستخدم النسخ المتفرّعة إما لاقتراح تغييرات على مشروع مستخدم آخر أو لاستخدام مشروع مستخدم آخر كنقطة بداية لفكرتك.

على سبيل المثال، يمكنك استخدام عمليات التفرّع لاقتراح تغييرات متعلّقة بإصلاح خطأ. لإصلاح خطأ برمجي، يمكنك اتّخاذ أحد الإجراءَين التاليَين:

  • أنشئ نسخة طبق الأصل من المستودع.
  • أصلِح المشكلة.
  • أرسِل طلب سحب إلى مالك المشروع.

خطوات إنشاء نسخة طبق الأصل من مستودع CFT:

  1. افتح متصفّح الويب وانتقِل إلى مستودع terraform-google-modules/terraform-google-cloud-storage. سنستخدم هذا المستودع طوال فترة Codelab.
  2. في أعلى يسار الصفحة، انقر على إنشاء نسخة.

9dc18f15ca662b56.png

  1. سيظهر لك خيار تحديد المكان الذي تريد إنشاء نسخة طبق الأصل فيه، اختَر ملفك الشخصي وسيتم إنشاء نسخة طبق الأصل من المستودع.

استنساخ نسخة من الشوكة محليًا

الفرع الذي أنشأته هو نسخة من مستودع وحدة GCS. عليك الآن استنساخ هذا المستودع إلى بيئتك المحلية لإضافة الميزة الجديدة.

خطوات استنساخ النسخة المتفرّعة:

  1. افتح متصفّح الويب وانتقِل إلى النسخة المتفرّعة على terraform-google-modules/terraform-google-cloud-storage.
  2. في أعلى يسار الشاشة، ستجد الزر "Code" (الرمز)، انقر عليه.

98f8be8df319dcd8.png

  1. بعد النقر على الزر "الرمز"، انقر على رمز "النسخ" لنسخ عنوان URL الخاص بالنسخة المتفرّعة. ستستخدم عنوان URL هذا لاستنساخ النسخة المتفرعة إلى بيئتك المحلية.

e61e1da6371f2a1d.png

  1. انتقِل إلى وحدة طرفية في VSCode أو على جهازك واستنسِخ النسخة المتفرّعة.
$ git clone <url>
# This command will clone your fork locally.
# Paste the copied URL from the previous step.
  1. بعد استنساخ النسخة المتفرّعة محليًا، عليك الانتقال إلى المستودع وإنشاء فرع جديد من النسخة المتفرّعة وإجراء تغييرات على الرمز في الفرع المؤقت.

يمكنك تسمية فرعك على النحو التالي:

  • بالنسبة إلى طلبات الميزات: feature/feature-name
  • بالنسبة إلى التحديثات الداخلية، internal/change-name
  • لإصلاح الأخطاء: bugfix/issue-name

بما أنّك تضيف ميزة جديدة، يمكنك تسمية الفرع المؤقت feature/silly_label

$ cd terraform-google-cloud-storage
# This command takes you into the cloned directory on your local machine.

$ git branch
# This command tells your current branch
# When you run this for the first time after you have cloned, your 
# output should say "master", that is your fork.

$ git checkout -b feature/silly_label
# This command creates a new branch on your fork and switches your 
# branch to the newly created branch.

$ git branch
# This command will confirm your current branch to be "feature/silly_label"

أصبحت الآن جاهزًا لبدء العمل على Cloud Foundation Toolkit.

4. إنشاء بيئة اختبار

تستند عملية تطوير CFT العادية إلى استخدام مشروع اختبار معزول لإجراء الاختبارات. ستوجّهك هذه الخطوة خلال عملية إنشاء المشروع التجريبي (استنادًا إلى إعدادات عادية) من خلال حساب خدمة.

0. تثبيت Docker Engine

إذا كنت تستخدم جهازك لأغراض التطوير، عليك تثبيت Docker Engine.

1. تثبيت Google Cloud SDK

لا تحتاج إلى تثبيت Google Cloud SDK إذا كنت تستخدم Cloud Shell في GCP.

انتقِل إلى Google Cloud SDK ونزِّل أداة التثبيت التفاعلية للنظام الأساسي الذي تستخدمه.

2- ضبط الإعدادات

لإنشاء بيئة اختبار، يجب أن يكون لديك مؤسسة على Google Cloud ومجلد اختبار وحساب فوترة. يجب ضبط هذه القيم من خلال متغيرات البيئة:

export TF_VAR_org_id="your_org_id"
export TF_VAR_folder_id="your_folder_id"
export TF_VAR_billing_account="your_billing_account_id"

3. إعداد حساب الخدمة

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

3.1 إنشاء مشروع Google Cloud Platform أو اختياره

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

gcloud config set core/project YOUR_PROJECT_ID

‫3.2 تفعيل واجهات برمجة التطبيقات في Google Cloud

فعِّل واجهات Google Cloud APIs التالية في مشروعك الأوّلي:

gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable iam.googleapis.com
gcloud services enable cloudbilling.googleapis.com

3.3 إنشاء حساب خدمة

أنشئ حساب خدمة جديدًا لإدارة بيئة الاختبار:

# Creating a service account for CFT.
gcloud iam service-accounts create cft-onboarding \
  --description="CFT Onboarding Terraform Service Account" \
  --display-name="CFT Onboarding"

# Assign SERVICE_ACCOUNT environment variable for later steps
export SERVICE_ACCOUNT=cft-onboarding@$(gcloud config get-value core/project).iam.gserviceaccount.com

تأكَّد من إنشاء حساب الخدمة باتّباع الخطوات التالية:

gcloud iam service-accounts list --filter="EMAIL=${SERVICE_ACCOUNT}"

‫3.4 منح حساب الخدمة أدوار "منشئ المشروع" و"مستخدم حساب الفوترة" و"مشاهد المؤسسة":

gcloud resource-manager folders add-iam-policy-binding ${TF_VAR_folder_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/resourcemanager.projectCreator"
gcloud organizations add-iam-policy-binding ${TF_VAR_org_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/billing.user"
gcloud beta billing accounts add-iam-policy-binding ${TF_VAR_billing_account} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/billing.user"
gcloud organizations add-iam-policy-binding ${TF_VAR_org_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/resourcemanager.organizationViewer"

يتوفّر لديك الآن حساب خدمة يمكن استخدامه لإدارة بيئة الاختبار.

4. إعداد بيانات اعتماد Terraform

لإنشاء بيئة الاختبار، عليك تنزيل مفتاح حساب الخدمة في shell.

4.1 مفتاح حساب الخدمة

إنشاء مفتاح حساب خدمة وتنزيله لـ Terraform

gcloud iam service-accounts keys create cft.json --iam-account=${SERVICE_ACCOUNT}

4.2 إعداد بيانات اعتماد Terraform

قدِّم المفتاح إلى Terraform باستخدام متغيّر البيئة SERVICE_ACCOUNT_JSON، مع ضبط القيمة على محتوى مفتاح حساب الخدمة.

export SERVICE_ACCOUNT_JSON=$(< cft.json)

بعد تخزين معلومات بيانات الاعتماد في متغيّر البيئة، أزِل ملف المفتاح. يمكنك إعادة إنشاء مفتاح لاحقًا إذا لزم الأمر باستخدام الأمر نفسه أعلاه.

rm -rf cft.json

5. إنشاء مشروع تجريبي لعمليات نشر Terraform

بعد إعداد كل شيء، يمكنك إنشاء مشروع الاختبار باستخدام أمر واحد. نفِّذ الأمر التالي من جذر دليل terraform-google-cloud-storage:

make docker_test_prepare

ستظهر لك النتيجة أدناه عند تنفيذ make docker_test_prepare ، وفي النهاية ستتلقّى رقم تعريف المشروع التجريبي الذي تم إنشاؤه والذي ستنفّذ فيه وحدة Cloud Storage وتختبرها باستخدام الميزة الجديدة. إذا واجهت مشاكل في ربط حساب فوترة، يمكنك الرجوع إلى خطوات تحديد المشاكل وحلّها.

macbookpro3:terraform-google-cloud-storage user$ make docker_test_prepare
docker run --rm -it \
                -e SERVICE_ACCOUNT_JSON \
                -e TF_VAR_org_id \
                -e TF_VAR_folder_id \
                -e TF_VAR_billing_account \
                -v /Users/cft/terraform-google-cloud-storage:/workspace \
                gcr.io/cloud-foundation-cicd/cft/developer-tools:0.8.0 \
                /usr/local/bin/execute_with_credentials.sh prepare_environment
Activated service account credentials for: [cft-onboarding@<project_id>.iam.gserviceaccount.com]
Activated service account credentials for: [cft-onboarding@<project_id>.iam.gserviceaccount.com]
Initializing modules...

Initializing the backend...

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.google-beta: version = "~> 3.9"
* provider.null: version = "~> 2.1"
* provider.random: version = "~> 2.2"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
module.project.module.project-factory.null_resource.preconditions: Refreshing state... [id=8723188031607443970]
module.project.module.project-factory.null_resource.shared_vpc_subnet_invalid_name[0]: Refreshing state... [id=5109975723938185892]
module.project.module.gsuite_group.data.google_organization.org[0]: Refreshing state...
module.project.module.project-factory.random_id.random_project_id_suffix: Refreshing state... [id=rnk]
module.project.module.project-factory.google_project.main: Refreshing state... [id=<project-id>]
module.project.module.project-factory.google_project_service.project_services[0]: Refreshing state... [id=<project-id>/storage-api.googleapis.com]
module.project.module.project-factory.google_project_service.project_services[1]: Refreshing state... [id=<project-id>/cloudresourcemanager.googleapis.com]
module.project.module.project-factory.google_project_service.project_services[2]: Refreshing state... [id=<project-id>/compute.googleapis.com]
module.project.module.project-factory.data.null_data_source.default_service_account: Refreshing state...
module.project.module.project-factory.google_service_account.default_service_account: Refreshing state... [id=projects/ci-cloud-storage-ae79/serviceAccounts/project-service-account@<project-id>.iam.gserv
iceaccount.com]
module.project.module.project-factory.google_project_service.project_services[3]: Refreshing state... [id=<project-id>/serviceusage.googleapis.com]
module.project.module.project-factory.null_resource.delete_default_compute_service_account[0]: Refreshing state... [id=3576396874950891283]
google_service_account.int_test: Refreshing state... [id=projects/<project-id>/serviceAccounts/cft-onboarding@<project-id>.iam.gserviceaccount.com]
google_service_account_key.int_test: Refreshing state... [id=projects/<project-id>/serviceAccounts/cft-onboarding@<project-id>.iam.gserviceaccount.com/keys/351009a1e011e88049ab2097994d1c627a61
6961]
google_project_iam_member.int_test[1]: Refreshing state... [id=<project-id>/roles/iam.serviceAccountUser/serviceaccount:cft-onboarding@<project-id>.iam.gserviceaccount.com]
google_project_iam_member.int_test[0]: Refreshing state... [id=<project-id>/roles/storage.admin/serviceaccount:cft-onboarding@<project-id>.iam.gserviceaccount.com]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

project_id = <test-project-id>
sa_key = <sensitive>
Found test/setup/make_source.sh. Using it for additional explicit environment configuration.

لقد أنشأت الآن مشروعًا تجريبيًا تتم الإشارة إليه من خلال project_id كما يمكنك أن ترى في ناتج وحدة التحكّم. تم إعداد بيئة التطوير والاختبار.

5- إضافة ميزة جديدة إلى وحدة CFT

بعد إعداد بيئة التطوير والاختبار، لنبدأ بإضافة ميزة "silly_label" إلى وحدة google-cloud-storage CFT.

تأكَّد من أنّك في terraform-google-cloud-storage وافتح الملف main.tf كما هو موضّح أدناه في بنية المجلد.

ac1dba25408abd09.png

بما أنّ "silly_label" هو تصنيف، ستضيف الميزة في السطر 27 في المتغيّر "labels" في ملف main.tf، كما هو موضّح أدناه:

terraform-google-cloud-storage/main.tf

resource "google_storage_bucket" "buckets" {
 <...>
 storage_class = var.storage_class
 // CODELAB:Add silly label in labels variable
 labels        = merge(var.labels, { name = replace("${local.prefix}${lower(each.value)}", ".", "-") }, { "silly" = var.silly_label })
 force_destroy = lookup(
 <...>
}

الآن، ستضيف المتغيّر silly_label في ملف variables.tf الذي يظهر في بنية المجلد أعلاه.

انسخ الرمز أدناه والصقه في السطر 31 في ملف variables.tf، وتأكَّد من إضافة حرف سطر جديد أعلى كتلة المتغيرات التي تضيفها وأسفلها.

terraform-google-cloud-storage/variables.tf

variable "names" {
 description = "Bucket name suffixes."
 type        = list(string)
}

// CODELAB: Add "silly_label" variable to variables.tf between "names" and "location"
variable "silly_label" {
 description = "Sample label for bucket."
 type        = string
}

variable "location" {
 description = "Bucket location."
 default     = "EU"
}

6. إضافة ميزة جديدة إلى مثال لحزمة تخزين

لقد أضفت ميزتك إلى ملف main.tf الخاص بالوحدة، والآن ستختبر الميزة المضافة من خلال مثال.

يجب إضافة "silly_label" إلى examples/multiple-buckets/main.tf.

سيتم استخدام هذا المثال في الخطوة التالية لإجراء اختبارات الدمج.

انسخ السطر التالي الخاص بالمتغيّر silly_label والصقه في السطر 27 في ملف main.tf في terraform-google-cloud-storage/examples/multiple-buckets/ كما هو موضّح في بنية المجلد:

5224fefbbcc61d89.png

terraform-google-cloud-storage/examples/multiple-buckets/main.tf

module "cloud_storage" {
 <...>
 // CODELAB: Add "silly_label" as an example to main.tf.
 silly_label        = "awesome"

 <..>
}

7. تعديل اختبار المخطط للتحقّق من الميزة

لقد أضفت ميزتك إلى ملف main.tf الخاص بالوحدة النمطية، ثم أضفت الميزة إلى مثال multiple_buckets. الآن، عليك اختبار الميزة من خلال اختبار تكاملي للمخطط مكتوب بلغة Golang.

ستضيف اختباراتك الجديدة في ملف multiple_buckets_test.go الذي يمكن العثور عليه في بنية المجلد أدناه:

72ea272d4792405.png

لقد أضفت التصنيف "silly_label" إلى جميع الحِزم التي يتم إنشاؤها من خلال وحدة multiple_buckets، وعليك الآن كتابة اختبارات لتجربة الميزة الجديدة.

في الرمز البرمجي أدناه، يمكنك الحصول على تصنيف كل حزمة من خلال الأمر gcloud alpha storage، ثم التحقّق من الناتج الذي تم عرضه من الأمر.

test/integration/multiple_buckets/multiple_buckets_test.go

func TestMultipleBuckets(t *testing.T) {
 <..>
op := gcloud.Run(t, fmt.Sprintf("alpha storage ls --buckets gs://%s", bucketName), gcloudArgs).Array()[0]

// verify silly label on each bucket
assert.Equal("awesome", op.Get("metadata.labels.silly").String(), "should have silly label set to awesome")

// verify lifecycle rules
...
}

8. تنفيذ اختبارات الدمج في CFT

اختبار التكامل

تُستخدَم اختبارات الدمج للتحقّق من سلوك الوحدة الرئيسية والوحدات الفرعية والأمثلة. يجب أن تكون الإضافات والتغييرات وعمليات الإصلاح مصحوبة باختبارات.

تتم كتابة اختبارات التكامل باستخدام إطار عمل اختبار المخطط ويتم تنفيذها باستخدام واجهة سطر الأوامر (CLI) في CFT. يتم تجميع هذه الأدوات في صورة Docker لتوفير الراحة.

تتمثّل الاستراتيجية العامة لهذه الاختبارات في التحقّق من سلوك الوحدات النموذجية، وبالتالي التأكّد من أنّ الوحدة الرئيسية والوحدات الفرعية والوحدات النموذجية كلها تعمل بشكل صحيح.

في التنفيذ التفاعلي، يتم تنفيذ كل خطوة من خلال أوامر متعددة.

  1. نفِّذ make docker_run لبدء حاوية Docker الاختبارية في وضع التفاعل.

‫Make هي أداة لإنشاء عمليات التشغيل المبرمَجة، وتعمل على إنشاء البرامج والمكتبات القابلة للتنفيذ تلقائيًا من رمز المصدر عن طريق قراءة الملفات التي تُسمى Makefiles والتي تحدّد كيفية استخلاص البرنامج المستهدَف. عند إجراء تغييرات على الملف، يجب تعديل حاوية Docker تلقائيًا.

عند تشغيل make docker_run، يمكنك إنشاء مساحة عمل في حاوية Docker وتفعيل بيانات اعتماد حساب الخدمة. سيتم استخدام مساحة العمل في الخطوات التالية لتنفيذ الاختبارات.

سيظهر لك الناتج التالي في الوحدة الطرفية:

Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
  1. نفِّذ الأمر module-swapper -registry-prefix=terraform-google-modules ​لتعديل ملفات المثال main.tf من أجل استيراد الوحدات من ملفاتك المحلية بدلاً من الوحدات المنشورة.

من المفترض أن تظهر لك نتيجة مثل ما يلي في الوحدة الطرفية:

[root@<CONTAINER_ID> workspace]# module-swapper -registry-prefix=terraform-google-modules
2025/08/04 19:26:29 Module name set from remote to cloud-storage
2025/08/04 19:26:29 Modifications made to file /workspace/examples/multiple_buckets/main.tf
2025/08/04 19:26:29 --- Original
+++ Modified
@@ -21,7 +21,7 @@
 }
 
 module "cloud_storage" {
-  source = "terraform-google-modules/cloud-storage/google"
+  source = "../.."
   # [restore-marker]   version = "~> 10.0"
 
   project_id = var.project_id
  1. نفِّذ الأمر cft test list لإدراج جميع اختبارات التصاميم في مساحة عملك.

سيظهر لك الناتج التالي في الوحدة الطرفية:

[root@CONTAINER_ID workspace]# cft test list
 NAME                           | CONFIG                    | LOCATION                                                   
--------------------------------+---------------------------+------------------------------------------------------------
 TestAll/examples/simple_bucket | examples/simple_bucket    | test/integration/discover_test.go                          
 TestMultipleBuckets            | examples/multiple_buckets | test/integration/multiple_buckets/multiple_buckets_test.go 

  1. نفِّذ cft test run <EXAMPLE_NAME> --stage init لتهيئة المثال. في هذه الحالة، عليك استبدال TestMultipleBuckets بـ cft test run TestMultipleBuckets --stage init لبدء تشغيل الاختبار. يمكنك أيضًا استخدام العلامة --verbose للحصول على معلومات إضافية عند إجراء الاختبارات.

تعمل مرحلة الإعداد هذه على إعداد مثال Terraform.

سيظهر لك الناتج أدناه في الوحدة الطرفية.

[root@<CONTAINER_ID> workspace]# cft test run TestMultipleBuckets --stage init --verbose
INFO[02-09|08:24:31] using test-dir: test/integration 
...
TestMultipleBuckets 2022-02-09T08:24:35Z command.go:179: Terraform has been successfully initialized!
...
TestMultipleBuckets 2022-02-09T08:24:35Z command.go:100: Running command terraform with args [validate]
TestMultipleBuckets 2022-02-09T08:24:36Z command.go:179: Success! The configuration is valid.
...
--- PASS: TestMultipleBuckets (4.05s)
  1. نفِّذ الأمر cft test run <EXAMPLE_NAME> --stage apply لتطبيق الوحدة النموذجية.

تطبّق هذه الخطوة المثال الذي تمّت تهيئته في المرحلة السابقة على مشروع GCP الذي تمّ إنشاؤه سابقًا في Codelab.

سيظهر لك الناتج أدناه في الوحدة الطرفية.

[root@<CONTAINER_ID> workspace]# cft test run TestMultipleBuckets --stage apply --verbose
INFO[02-09|08:28:11] using test-dir: test/integration
...
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179: Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179: 
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179: Outputs:
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179: 
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179: names = {
TestMultipleBuckets 2022-02-09T08:28:19Z command.go:179:   "one" = "multiple-buckets-erp1-eu-one"
...
--- PASS: TestMultipleBuckets (6.51s)
PASS
ok      github.com/terraform-google-modules/terraform-google-cloud-storage/test/integration/multiple_buckets    6.548s
  1. نفِّذ الأمر cft test run <EXAMPLE_NAME> --stage verify للتحقّق من أنّ المثال الذي تم إنشاؤه يتضمّن البنية الأساسية المتوقّعة.

ستنفّذ هذه الخطوة وظيفة التحقّق في TestMultipleBuckets. عادةً ما يتم إجراء عملية التحقّق من خلال تنفيذ أمر gcloud لاسترداد إخراج JSON للحالة الحالية لأحد الموارد والتأكّد من أنّ الحالة الحالية هي كما هو موضّح في المثال.

إذا ظهرت لك أي أخطاء، ستظهر لك النتيجة المتوقّعة والنتيجة التي تلقّاها الأمر للاختبار.

سيظهر لك الناتج أدناه في الوحدة الطرفية.

[root@<CONTAINER_ID> workspace]# cft test run TestMultipleBuckets --stage verify --verbose
INFO[02-09|08:30:19] using test-dir: test/integration
...
TestMultipleBuckets 2022-02-09T08:30:27Z command.go:100: Running command terraform with args [output -no-color -json names_list]
TestMultipleBuckets 2022-02-09T08:30:27Z command.go:179: ["multiple-buckets-erp1-eu-one","multiple-buckets-erp1-eu-two"]
TestMultipleBuckets 2022-02-09T08:30:27Z command.go:100: Running command gcloud with args [alpha storage ls --buckets gs://multiple-buckets-erp1-eu-one --project ci-cloud-storage-8ce9 --json]
TestMultipleBuckets 2022-02-09T08:30:28Z command.go:179: [
TestMultipleBuckets 2022-02-09T08:30:28Z command.go:179: {
TestMultipleBuckets 2022-02-09T08:30:28Z command.go:179:   "url": "gs://multiple-buckets-erp1-eu-one/",
...
TestMultipleBuckets 2022-02-09T08:30:33Z command.go:179: ]
2022/02/09 08:30:33 RUN_STAGE env var set to verify
2022/02/09 08:30:33 Skipping stage teardown
--- PASS: TestMultipleBuckets (12.32s)
PASS
ok      github.com/terraform-google-modules/terraform-google-cloud-storage/test/integration/multiple_buckets    12.359s
  1. نفِّذ الأمر cft test run <EXAMPLE_NAME> --stage teardown لإيقاف المثال.

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

يمكنك الاطّلاع على الناتج أدناه في الوحدة الطرفية.

[root@<CONTAINER_ID> workspace]# cft test run TestMultipleBuckets --stage teardown --verbose
INFO[02-09|08:36:02] using test-dir: test/integration
...
TestMultipleBuckets 2022-02-09T08:36:06Z command.go:100: Running command terraform with args [destroy -auto-approve -input=false -lock=false]
TestMultipleBuckets 2022-02-09T08:36:07Z command.go:179: module.cloud_storage.random_id.bucket_suffix: Refreshing state... [id=mNA]
TestMultipleBuckets 2022-02-09T08:36:07Z command.go:179: random_string.prefix: Refreshing state... [id=erp1]
TestMultipleBuckets 2022-02-09T08:36:08Z command.go:179: module.cloud_storage.google_storage_bucket.buckets["two"]: Refreshing state... [id=multiple-buckets-erp1-eu-two]
...
TestMultipleBuckets 2022-02-09T08:36:10Z command.go:179: Destroy complete! Resources: 6 destroyed.
TestMultipleBuckets 2022-02-09T08:36:10Z command.go:179: 
--- PASS: TestMultipleBuckets (6.62s)
PASS
ok      github.com/terraform-google-modules/terraform-google-cloud-storage/test/integration/multiple_buckets    6.654s
  1. نفِّذ الأمر module-swapper -registry-prefix=terraform-google-modules -restore ​للتراجع عن التعديلات التي أجريتها على ملفات المثال main.tf في آخر مرة نفَّذت فيها الأمر module-swapper.
[root@<CONTAINER_ID> workspace]# module-swapper -registry-prefix=terraform-google-modules -restore
2025/08/04 19:30:41 Module name set from remote to cloud-storage
2025/08/04 19:36:32 Modifications made to file /workspace/examples/multiple_buckets/main.tf
2025/08/04 19:36:32 --- Original
+++ Modified
@@ -21,8 +21,8 @@
 }
 
 module "cloud_storage" {
-  source = "../.."
-   version = "~> 10.0"
+  source  = "terraform-google-modules/cloud-storage/google"
+  version = "~> 10.0"
 
   project_id = var.project_id
 
  1. نفِّذ الأمر exit للخروج من الحاوية الاختبارية.

9- إنشاء مستندات للمدخلات والمخرجات

يتم إنشاء جدولتَي "المدخلات" و"المخرجات" في ملفات README الخاصة بالوحدة الرئيسية والوحدات الفرعية ووحدات الأمثلة تلقائيًا استنادًا إلى variables وoutputs للوحدات المعنية. يجب إعادة تحميل هذه الجداول في حال تغيير واجهات الوحدات.

التشغيل:

make generate_docs
# This will generate new Inputs and Outputs tables

10. تنفيذ اختبارات lint في CFT

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

يمكن إجراء تدقيق نحوي أو تنسيق للعديد من الملفات في المستودع للحفاظ على مستوى جودة موحّد. لضمان الجودة في CFT، ستستخدم اختبار lint.

التشغيل:

make docker_test_lint
# This will run all lint tests on your repo

11. إرسال طلب سحب على Github

بعد أن غيّرت الرمز برمجيًا على جهازك واختبرته من خلال اختبارات الدمج، عليك نشره في مستودع الرموز البرمجية الرئيسي.

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

عند إرسال طلب سحب، سيتم إعلام مشرف المستودع لمراجعة التغييرات المقترَحة على الرمز. بالإضافة إلى ذلك، يمكنك أيضًا إضافة مستخدمين آخرين كمراجعين للحصول على ملاحظات حول تغييرات الرمز البرمجي. سيؤدي طلب السحب إلى تشغيل Cloud Build الذي سيجري اختبارات على المستودع.

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

نفِّذ الخطوات التالية لتثبيت الرمز في الفرع المتفرّع ودفع الرمز إلى الفرع المتفرّع:

  1. الخطوة الأولى هي إضافة الملفات التي تم تغييرها إلى المستودع المحلي.
$ git add main.tf
$ git add README.md
$ git add variables.tf
$ git add examples/multiple-buckets/main.tf
$ git add test/integration/multiple_buckets/multiple_buckets_test.go
# The ‘git add' command adds the file in the local repository and 
# stages the file for commit. To unstage a file, use git reset HEAD YOUR-FILE
  1. تمت الآن إضافة ملفاتك إلى منطقة التخزين المؤقت، والخطوة التالية هي تثبيت التغييرات.
$ git commit -m "First CFT commit"
# This will commit the staged changes and prepares them to be pushed 
# to a remote repository. To remove this commit and modify the file, 
# use 'git reset --soft HEAD~1' and commit and add the file again.
  1. ادفع التغييرات التي تمّت في مستودعك المحلّي إلى GitHub لإنشاء طلب سحب (PR).
$ git push -u origin feature/silly_label
# Pushes the changes in your local repository up to the remote
# repository you specified as the origin

أصبحت تغييرات الرمز البرمجي جاهزة الآن لطلب سحب.

اتّبِع الخطوات التالية لإنشاء طلب سحب إلى مستودع terraform-google-modules/terraform-google-cloud-storage:

  1. في متصفّح الويب، انتقِل إلى الصفحة الرئيسية repo.
  2. سيظهر لك اقتراح من خلال بانر لفتح طلب سحب من نسختك المتفرّعة. انقر على "مقارنة وطلب سحب".

60e7ae0cbc11588e.png

  1. أدخِل عنوانًا ووصفًا لطلب السحب من أجل وصف التغييرات في الرمز. يُرجى تقديم معلومات دقيقة وموجزة قدر الإمكان.

f4302385e9e1776a.png

  1. لإنشاء طلب سحب جاهز للمراجعة، انقر على "إنشاء طلب سحب".
  2. ستظهر لك مشغّلات Cloud Build تعمل بسبب طلب السحب.
  3. يمكنك الرجوع إلى مستندات GitHub الرسمية حول فتح طلبات السحب من النسخ المتفرعة في حال مواجهة أي مشاكل.

لقد دفعت بنجاح أول تغيير في الرمز إلى فرعك المتفرّع وأنشأت أول طلب سحب في CFT مقابل الفرع الرئيسي.

12. تهانينا

تهانينا، لقد أضفت ميزة بنجاح إلى وحدة CFT وأرسلت طلب دمج للمراجعة.

أضفت ميزة إلى وحدة CFT واختبرتها محليًا من خلال مثال، وأجريت اختبارات قبل إرسال الرمز إلى GitHub. أخيرًا، أرسلت طلب سحب للمراجعة والدمج النهائي في CFT.

أصبحت الآن على دراية بالخطوات المهمة للبدء باستخدام Cloud Foundation Toolkit.