# بنية الكود

الأسئلة المتعلقة ببنية كود Terraform هي الأكثر شيوعًا في المجتمع. في الكثير من الأحيان فكر الجميع في أفضل بنية كود ممكن الحصول عليها  للمشروع.

## كيف يجب هيكلة مشروع Terraform؟

هذا نوع من الأسئلة التي يمكن الإجابة عليها بالعديد من الطرق ومن الصعب جداً تقديم نصيحة تنفع لجميع الحالات، لذلك لنبدأ بفهم ما نتعامل معه.

* ما هو مدى تعقيد مشروعك؟
  * عدد الموارد المرتبطة ببعضها
  * عدد الموفرين (انظر الملاحظة أدناه عن "logical providers")
* &#x20;كم مرة تحتاج إلى تغيير في البنية التحتية؟
  * **من** مرة في الشهر/الأسبوع/اليوم؟
  * **إلى** تغيير مستمر (عند كل commit جديدة)
* مصادر تغيير الكود، هل تسمح لمخدم CI بتعديل repository عند بناء artifact جديدة؟
  * يسمح فقط للمطورين بإضافة تغييرات إلى repository الخاصة بالبنية التحتية
  * يسمح لأي أحد باقتراح تغيير من خلال فتح PR (متضمناً المهام الأتوماتيكية التي يقوم بها مخدم CI)
* ما هي المنصة أو الخدمة التي تستعملها لعملية deployment؟
  * &#x20;AWS CodeDeploy, Kubernetes, OpenShift (يحتاج كل حل إلى معاملة مختلفة)
* كيف يتم فرز البيئات المختلفة؟
  * من خلال بيئة العمل(environment)، المنطقة (region)، المشروع (project)

{% hint style="info" %}
*Logical providers*

هي الموفرات التي تعمل كلياً ضمن Terraform ولا تتعامل غالباً مع أي خدمة خارجية، لذا يمكن أن نعتبرها أدوات بتعقيد O(1). أكثر هذه الموفرات شهرة هي [random](https://registry.terraform.io/providers/hashicorp/random/latest/docs), [local](https://registry.terraform.io/providers/hashicorp/local/latest/docs), [terraform](https://www.terraform.io/docs/providers/terraform/index.html), [null](https://registry.terraform.io/providers/hashicorp/null/latest/docs), [time](https://registry.terraform.io/providers/hashicorp/time/latest).
{% endhint %}

## مقدمة إلى هيكلة مشروع Terraform

عند بداية التعامل مع Terraform أو عندما تريد أن تكتب مثالاً فإن وضع كل الكود في ملف `main.tf` تعتبر فكرة جيدة، ولكن في كل الحالات الأخرى يجب تقسيم الكود منطقياً إلى ملفات مختلفة كالتالي:

* ملف `main.tf`, والذي يستدعي الوحدات المختلفة (modules), والوسطاء المحلية (locals)، ومصادر البيانات (data) لتوليد كافة الموارد (resources)
* &#x20;ملف `variables.tf`، الذي يحتوي على تعريف للوسطاء (variables) المراد استعمالها في`main.tf`&#x20;
* ملف`outputs.tf`، الذي يعرف خرج الموارد المولدة من قبل`main.tf`&#x20;
* ملف`versions.tf` ، الذي يحتوي متطلبات الإصدار الخاصة بـ Terraform و الموفرين

لا يجب استعمال `terraform.tfvars`في أي مكان ما عدا [composition](https://antonbabenko.gitbook.io/ar/key-concepts#altrkyb-composition).

## كيف يجب أن نفكر عند هيكلة مشروع Terraform

{% hint style="info" %}
الرجاء التأكد من فهم المفاهيم الرئيسية [resource module](/ar/key-concepts.md#resource-module), [infrastructure module](/ar/key-concepts.md#infrastructure-module), [composition](/ar/key-concepts.md#composition) لأهميتها لفهم الأمثلة التالية &#x20;
{% endhint %}

### التوصيات العامة لهيكلة الكود&#x20;

* إنه من الأسهل والأسرع التعامل مع عدد قليل من الموارد
  * إن كل من تعليمتي `terraform plan`و`terraform apply` تقوم باستدعاء cloud API للتحقق من حالة الموارد
  * إذا كانت كل بنيتك التحتية في تركيب واحد ستأخذ هذه التعليمات وقتاً طويلاً للتنفيذ
* مدى الضرر يكون أصغر في حال تعريف موارد قليلة
  * عزل الموارد غير المرتبطة ببعضها في تراكيب مختلفة يقلل الخطر في حال حدوث مشكلة ما
* استعمل ملف الحالة المخرن عن بعد
  * حاسبك الشخصي لا يمثل عكس لحقيقة البنية التحتية
  * إدارة tfstate في git أمر كارثي
  * لاحقاً عند توسع البنية في اتجاهات عدة (عدد الموارد وعدد dependencies)، سيكون استعمال هذا الملف أسهل للتحكم بهذه البنية
* &#x20;تمرن على بنية وطرق تسمية متسقة
  * مثل الكود العادي، فإن كود Terraform يجب أن يكون مقروءاً، الاتساق سيساعد عندما تريد التحقق من تعديلات تمت إضافتها من 6 أشهر ماضية
  * من الممكن أن تنقل موارد لم يتم تعريفها سابقاً إلى ملف Terraform State، لكن وجود كود غير متسق سيصعب الأمر &#x20;
* قم ببناء وحدة (modules) بسيطة قدر الإمكان
* لا تقم باستعمال قيم ثابتة (hardcoded) إذا كنت تستطيع تمريرها كمتحول أو الحصول عليها من مصدر بيانات
* استعمل مصادر البيانات و `terraform_remote_state` كغراء بين وحدات البنية التحتية في التركيب

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

### تنسيق وحدات وتركيبات البنى التحتية

وجود بنية تحتية صغيرة يعني وجود عدد صغير من الاعتماديات (dependencies) والموارد، كلما كبر المشروع فإن أهمية ربط البنى المختلفة وتمرير المتحولات في التركيب تصبح واضحة اكثر.

يوجد على الأقل 5 أدوات تنسيقات مستقلة التي يمكن للمطور أن يستعملها:

1. يكفي للمطور أن يستعمل Terraform
2. &#x20; استعمال  أداة Terragrunt، وهي أداة orchestration تستعمل لتنسيق كل البنية التحتية والاعتماديات، تعمل هذه الأداة مع مختلف الوحدات (modules) والتراكيب (compositions) لذلك تخفف من تكرار الكود (إعادة اختراع العجلة)
3. استعمال scripts خاصة بالشركة (In-house scripts)، تم استعمالها كبداية لعمليات التنسيق قبل صدور Terragrunt
4. استعمال أداة Ansible أو أي أداة أتمتة (Autoamtion tools) . يتم استعمالها في حال تم تبني Terraform بعد استعمال Ansible، أو في حال استعمال Ansible UI.
5. &#x20;أستعمال أداة [Crossplane](https://crossplane.io/) و الأدوات الملهمة من قبل Kubernetes. من المنطقي أحياناً استعمال Kubernetes لتنسيق Terraform.  لمزيد من المعلومات شاهد هذا الفيديو   [Crossplane vs Terraform](https://www.youtube.com/watch?v=ELhVbSdcqSY)&#x20;

في هذا الكتاب نقوم فقط بعرض الحلين الأولين (Terraform only and Terragrunt.)

شاهد أمثلة عن  [Terraform](/ar/examples/terraform.md) أو [Terragrunt](/ar/examples/terragrunt.md) في الفصل القادم&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.terraform-best-practices.com/ar/code-structure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
