ورشة عمل أساسية 2 — Terraform: تعديل، استبدال، حذف

تدريب موجَّه13 دقيقة

pratique: true

الورشة الأساسية 2 — Terraform : تعديل، استبدال، تدمير

المدة
20 دقيقة
الوحدة
1/7
المتطلبات المسبقة
الورشة الأساسية 1 منتهية، بدون destroy : يحتوي المجلد travail/atelier-1 على main.tf وbonjour.txt وterraform.tfstate، ويجيب terraform state list فيه بـ local_file.bonjour
ستبني
لا شيء جديدًا ؛ ستُحيي ما أنشأته : تكسره يدويًا، وتراه يُصلَح، وتغيّر محتواه، وتراه يُستبدَل، ثم تدمّر كل شيء حتى الوصول إلى state فارغ
المخرج المطلوب
مخرجات terraform plan من الخطوة 5 (التي تحتوي على must be replaced) ومخرجات terraform state list من الخطوة 9 (فارغة)

كيف تقرأ هذه الصفحة. عشر خطوات، أمر واحد في كل مرة. لكل منها : الأمر، والمخرجات الدقيقة لجهاز الدورة (Terraform 1.12.2)، وما يجب النظر إليه. اكتب كل أمر بنفسك. كتل « لفهم أفضل » اختيارية. أوامر terraform … متطابقة في كل مكان ؛ وعندما يعتمد أمر على النظام، تُعطى النسختان، إحداهما تحت الأخرى. إذا لم يعد مجلد الورشة 1 موجودًا أو إذا لم يجب state list بـ local_file.bonjour، فأعد الورشة الأساسية 1 أولًا (العُدّة : https://github.com/hrhouma2/aiopsatlas-terraform-labo-fr).

الهدف

جعلتك الورشة 1 تُنشئ موردًا وتقرأ state. لكن البنية التحتية لا تُنشأ مرة واحدة وإلى الأبد : تُعدَّل، ويكسرها أحد سهوًا، ويومًا ما تُفكَّك. هذه هي الحركات الثلاث لهذه الورشة. ستحذف أولًا bonjour.txt يدويًا، كزميل « ينظّف » مجلدًا، وترى Terraform يلاحظ ذلك ثم يعيد إنشاءه : هذا هو الانحراف من الدرس 01. ثم ستغيّر سطرًا في main.tf وتكتشف أن، بالنسبة للمزوّد local، تغيير محتوى ملف لا يعدّله : بل يستبدله، برمز يجب أن تعرف التعرّف عليه قبل أن تقول yes. وأخيرًا ستدمّر كل شيء، وتتحقق من أن السجل فارغ وأن العُدّة تعدّ صفرًا.

المفردات في صورة واحدة

دائمًا المهندس المعماري. الانحراف (drift) هو عامل حرّك جدارًا دون أن يقول : لم يعد المبنى مطابقًا للسجل ؛ يلاحظ المهندس ذلك عندما يذهب ليرى في الموقع (Refreshing state...). التعديل في المكان (~) هو إعادة طلاء جدار : يبقى الجدار نفسه. الاستبدال (-/+) هو هدم الجدار وإعادة بناء واحد في المكان نفسه : له رقم جديد في السجل. التدمير (-) هو الهدم دون إعادة البناء. يقول الكشف دائمًا أيًّا من الثلاثة يتوقع ؛ وأنت تقرأه قبل التوقيع.

الرمز في الخطةالجملة في الخطةما يفعله Terraformفي هذه الورشة
+will be createdينشئ كائنًا جديدًاالخطوة 3 : الملف المحذوف يدويًا
~will be updated in-placeيغيّر خاصية، ويبقى الكائنأبدًا لـ content في local_file
-/+must be replacedيدمّر الكائن، ثم ينشئ آخرالخطوة 5 : content يتغيّر
-will be destroyedيحذف الكائنالخطوة 8 : destroy

أين تكتب

الطرفية نفسها كما في الورشة 1، في المجلد travail/atelier-1 من العُدّة lab-terraform. وVS Code لتعديل main.tf. أوامر terraform … متطابقة في كل مكان ؛ وأوامر حذف ملف أو قراءته أو سرده تُعطى في النسختين.

الخطوة 1 — استعادة نقطة البداية

Windows (PowerShell)، من جذر العُدّة :

powershell
cd travail\atelier-1

Linux وmacOS وWSL 2 وGit Bash :

bash
cd travail/atelier-1

ثم :

text
terraform state list
text
local_file.bonjour

ما يطلبه الأمر : « ماذا تدير في هذا المجلد ؟ »

ما يجب النظر إليه : سطر واحد، local_file.bonjour. هذه الحالة التي تركتك فيها الورشة 1. إذا قرأت No state file was found! أو لا شيء على الإطلاق، فالمجلد ليس الصحيح أو المورد دُمّر : أعد الورشة 1 قبل المتابعة.

الخطوة 2 — الكسر يدويًا

Windows (PowerShell) :

powershell
Remove-Item .\bonjour.txt
Get-ChildItem

Linux وmacOS وWSL 2 وGit Bash :

bash
rm bonjour.txt
ls

ما تطلبه الأوامر : « احذف bonjour.txt، ثم أرِني المجلد. »

ما يجب النظر إليه : لم يعد bonjour.txt موجودًا ؛ وmain.tf وterraform.tfstate ما زالا هناك. لقد فعلت للتو ما يفعله زميل في وحدة تحكم AWS عندما يحذف bucket « لم يكن يفيد بشيء » : تغيّر الواقع، لكن لا الشيفرة ولا السجل يعرفان ذلك بعد.

الخطوة 3 — رؤية الانحراف

text
terraform plan
text
local_file.bonjour: Refreshing state... [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]

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:

  # local_file.bonjour will be created
  + resource "local_file" "bonjour" {
      + content              = "Bonjour Terraform"
      + content_base64sha256 = (known after apply)

      + filename             = "./bonjour.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

ما يطلبه الأمر : « قارن الشيفرة والسجل والواقع، وقل لي ما ينقص. »

ما يجب النظر إليه : Refreshing state... [id=fd9aee55…] : ذهب Terraform ليرى الملف الذي يذكره سجله، ولم يجده. النتيجة : يحذفه من سجله ويقول الكشف will be created، Plan: 1 to add. الخطة نفسها كما في الورشة 1، الخطوة 5، مع أنك لم تمسّ الشيفرة. هذا هو الانحراف : تحرّك الواقع دون المرور بـ Terraform، وكشفه Terraform لحظة الخطة، لا قبلها.

لفهم أفضل
  • لا يراقب Terraform شيئًا بشكل مستمر. بين أمرَين، لا يعرف ما يحدث. Refreshing state... في plan (وفي apply) هو ما يعيد قراءة الواقع. ملف حُذف منذ ثلاثة أيام لا يُكتشف إلا في plan التالي.
  • لماذا + وليس -/+ ؟ لم يعد الكائن موجودًا على الإطلاق : لا شيء لتدميره، فقط للإنشاء. -/+ (الخطوة 5) لكائن ما زال موجودًا لكن يجب إعادة صنعه.
  • في السحابة، هذا الموقف الأكثر شيوعًا : عدّل أحدهم قاعدة جدار ناري في وحدة التحكم، ويقترح plan التالي إعادتها كما تقول الشيفرة. تُظهر لك الخطة ذلك ؛ وعليك أن تقرّر ما إذا كانت الشيفرة أو وحدة التحكم هي التي كانت على حق.

الخطوة 4 — الإصلاح

text
terraform apply
text
local_file.bonjour: Refreshing state... [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]



Plan: 1 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

local_file.bonjour: Creating...
local_file.bonjour: Creation complete after 0s [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]

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

ما يطلبه الأمر : « أعد حساب الكشف، انتظر yes مني، ثم نفّذه. »

ما يجب النظر إليه : عاد bonjour.txt، وid الخاص به هو نفسه كما قبل (fd9aee55…) : معرّف local_file هو بصمة محتواه، والمحتوى لم يتغيّر. تحقق بـ Get-Content .\bonjour.txt أو cat bonjour.txt : Bonjour Terraform. لم يكن سكربت ليعرف أنه يجب الإصلاح ؛ عرف Terraform ذلك لأن لديه سجلًا وشيفرة للمقارنة.

الخطوة 5 — تغيير المحتوى، قراءة كشف الاستبدال

في VS Code، عدّل سطر content في main.tf للحصول على :

hcl
resource "local_file" "bonjour" {
  filename = "${path.module}/bonjour.txt"
  content  = "Bonjour Terraform, deuxième version"
}

احفظ، ثم :

text
terraform plan
text
local_file.bonjour: Refreshing state... [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # local_file.bonjour must be replaced
-/+ resource "local_file" "bonjour" {
      ~ content              = "Bonjour Terraform" -> "Bonjour Terraform, deuxième version" # forces replacement
      ~ content_base64sha256 = "SvXkP5Iqo1rJKHgTVJnjanxfsNVGhb+r52mzUqZJYyg=" -> (known after apply)
      ~ content_base64sha512 = "r3+PevYNJRFsHMz4H4U1DK+lg89nhO9SLJZMAqqtzPKiIv3ilrmbx5sYh2JCW9o5EF0NXanYmuxMvI2QN4Z1Ag==" -> (known after apply)
      ~ content_md5          = "ff3a967c227a58691a3d34a931d3eeb5" -> (known after apply)
      ~ content_sha1         = "fd9aee5556589b4d797e6d49f8ec894e29e57713" -> (known after apply)
      ~ content_sha256       = "4af5e43f922aa35ac92878135499e36a7c5fb0d54685bfabe769b352a6496328" -> (known after apply)
      ~ content_sha512       = "af7f8f7af60d25116c1cccf81f85350cafa583cf6784ef522c964c02aaadccf2a222fde296b99bc79b188762425bda39105d0d5da9d89aec4cbc8d9037867502" -> (known after apply)
      ~ id                   = "fd9aee5556589b4d797e6d49f8ec894e29e57713" -> (known after apply)
        # (3 unchanged attributes hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

ما يطلبه الأمر : الطلب نفسه كما في الخطوة 3. لكن هذه المرة الشيفرة هي التي تغيّرت، لا الواقع.

ما يجب النظر إليه، سطرًا سطرًا. هذه أهم خطة في الوحدة :

السطرما يقوله
-/+ destroy and then create replacementالمفتاح : الرمز المستخدم هو -/+، « تدمير ثم إنشاء بديل ».
# local_file.bonjour must be replacedليس will be updated in-place : المورد يجب استبداله.
-/+ resource "local_file" "bonjour" {تحمل الكتلة بأكملها -/+.
~ content = "Bonjour Terraform" -> "Bonjour Terraform, deuxième version" # forces replacementيقول ~ إن القيمة تتغيّر، من القديمة (->) إلى الجديدة. ويقول التعليق # forces replacement إن هذه الخاصية هي التي تُلزم بالاستبدال.
~ content_md5 = "ff3a967c…" -> (known after apply)ستتغيّر البصمات ؛ لا يعرف Terraform الجديدة بعد.
~ id = "fd9aee55…" -> (known after apply)سيتغيّر المعرّف. سيكون كائنًا آخر.
# (3 unchanged attributes hidden)filename وdirectory_permission وfile_permission لا تتحرك ؛ يخفيها Terraform من أجل القراءة.
Plan: 1 to add, 0 to change, 1 to destroy.تدمير واحد وإنشاء واحد، صفر تعديل.

هذا هو مخرجك المطلوب الأول : احتفظ بهذه المخرجات.

الفرق الجوهري بين ~ و-/+. يقول ~ أمام content ماذا يتغيّر. ويقول -/+ أمام resource كيف سيتصرف Terraform : الهدم، ثم إعادة البناء. بالنسبة لملف نصي، لن ترى الفرق. أما بالنسبة لقاعدة بيانات، فـ -/+ يعني أن البيانات تختفي مع الكائن القديم. المزوّد هو من يقرّر، خاصيةً خاصية ؛ وقد قرّر المزوّد local أن content يفرض الاستبدال. وأنت تقرأ المؤشرات الثلاثة (must be replaced، # forces replacement، 1 to destroy) قبل كتابة yes.

لفهم أفضل
  • لماذا يستبدل المزوّد local بدلًا من التعديل ؟ لأنه لا يعرف « تصحيح » ملف موجود : يعرف كتابته أو محوه. وid الخاص بـ local_file هو أصلًا بصمة SHA-1 لمحتواه ؛ تغيير المحتوى يغيّر المعرّف، وكائن يتغيّر معرّفه هو، بالنسبة لـ Terraform، كائن آخر. على جهاز الدورة، يفرض file_permission الاستبدال أيضًا. تتصرف مزوّدات أخرى بشكل مختلف : تغيير وسم (tag) على مورد AWS هو ~، وتغيير اسمه غالبًا -/+.
  • أين هذا مكتوب ؟ في وثائق كل مورد على الـ Registry، تُوسَم بعض الوسائط بـ forces new resource (أو ForceNew). قبل apply في الإنتاج، هذا ما سنقرأه.
  • هل يمكن إجبار استبدال عن قصد ؟ نعم : terraform apply -replace=local_file.bonjour يستبدل المورد حتى دون تغيير في الشيفرة. مفيد عندما يكون كائن معطوبًا. ستراه في المشروع 08.

الخطوة 6 — تطبيق الاستبدال

text
terraform apply
text
local_file.bonjour: Refreshing state... [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]



Plan: 1 to add, 0 to change, 1 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

local_file.bonjour: Destroying... [id=fd9aee5556589b4d797e6d49f8ec894e29e57713]
local_file.bonjour: Destruction complete after 0s
local_file.bonjour: Creating...
local_file.bonjour: Creation complete after 0s [id=bd2b5f8ccbb2cbc2b9bea872211549635a76b092]

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

ما يطلبه الأمر : الطلب نفسه كما في الخطوة 4.

ما يجب النظر إليه : أربعة أسطر إجراء بدلًا من سطرَين، بترتيب الرمز -/+ : Destroying... ثم Destruction complete (القديم، fd9aee55…)، ثم Creating... ثم Creation complete (الجديد، bd2b5f8c…). والسطر الأخير : Apply complete! Resources: 1 added, 0 changed, 1 destroyed. ليس 1 changed : لم يُعدَّل شيء، دُمّر كائن وأُنشئ آخر.

الخطوة 7 — التحقق من الملف والمعرّف الجديد

Windows (PowerShell) :

powershell
Get-Content .\bonjour.txt

Linux وmacOS وWSL 2 وGit Bash :

bash
cat bonjour.txt
text
Bonjour Terraform, deuxième version

ثم :

text
terraform state show local_file.bonjour
text
# local_file.bonjour:
resource "local_file" "bonjour" {
    content              = "Bonjour Terraform, deuxième version"
    content_base64sha256 = "hg9L75JxH+5SDk+ZOADZinGONkirydetS0TFjN3uZ3o="
    content_base64sha512 = "EjT8mRVQU2JQ+Em/rnbRKYfe7E2UqIWw8yQMMtaatimH5XCKg4ZomW4PI5yO5jhujdSrU04vX17HE2kaqEVSkQ=="
    content_md5          = "9a1a1355b48e28ad727200e450b851e1"
    content_sha1         = "bd2b5f8ccbb2cbc2b9bea872211549635a76b092"
    content_sha256       = "860f4bef92711fee520e4f993800d98a718e3648abc9d7ad4b44c58cddee677a"
    content_sha512       = "1234fc991550536250f849bfae76d12987deec4d94a885b0f3240c32d69ab62987e5708a838668996e0f239c8ee6386e8dd4ab534e2f5f5ec713691aa8455291"
    directory_permission = "0777"
    file_permission      = "0777"
    filename             = "./bonjour.txt"
    id                   = "bd2b5f8ccbb2cbc2b9bea872211549635a76b092"
}

ما تطلبه الأوامر : « أرِني الملف الحقيقي، ثم ما يقوله السجل عنه. »

ما يجب النظر إليه : يحتوي الملف على النسخة الثانية. في السجل، content هو القيمة الجديدة، وتغيّرت كل البصمات، وid هو bd2b5f8c…، الذي عرضه Creation complete في الخطوة 6. قارن مع state show من الورشة 1، الخطوة 9 : العنوان نفسه local_file.bonjour، لكن كائن آخر. الشيفرة والسجل والواقع متفقة مجددًا : terraform plan الآن سيقول No changes.

الخطوة 8 — تدمير كل شيء

text
terraform destroy
text
local_file.bonjour: Refreshing state... [id=bd2b5f8ccbb2cbc2b9bea872211549635a76b092]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # local_file.bonjour will be destroyed
  - resource "local_file" "bonjour" {
      - content              = "Bonjour Terraform, deuxième version" -> null
      - content_base64sha256 = "hg9L75JxH+5SDk+ZOADZinGONkirydetS0TFjN3uZ3o=" -> null

      - filename             = "./bonjour.txt" -> null
      - id                   = "bd2b5f8ccbb2cbc2b9bea872211549635a76b092" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

local_file.bonjour: Destroying... [id=bd2b5f8ccbb2cbc2b9bea872211549635a76b092]
local_file.bonjour: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

ما يطلبه الأمر : « دمّر كل ما تديره هنا ؛ أرِني الكشف وانتظر yes مني. »

ما يجب النظر إليه : الرمز الثالث، - وحده، وكل خاصية تنتقل إلى -> null (« لا شيء بعد الآن »). السؤال أخطر مما في apply : Do you really want to destroy all resources? وThere is no undo. اكتب yes. الجملة المنتظرة : Destroy complete! Resources: 1 destroyed. اختفى الملف من المجلد.

الخطوة 9 — قراءة سجل فارغ

text
terraform state list
text

ثم، لترى بماذا يجيب Terraform عندما نطلب منه موردًا لم يعد يديره :

text
terraform state show local_file.bonjour
text
No instance found for the given address!

This command requires that the address references one specific instance.
To view the available instances, use "terraform state list". Please modify
the address to reference a specific instance.

ما تطلبه الأوامر : « اسرد ما تديره »، ثم « أرِني local_file.bonjour ».

ما يجب النظر إليه : لا يجيب state list بـشيء : لا سطر، لا خطأ، سجل فارغ. هذا مختلف عن No state file was found! من الورشة 1 قبل apply : هنا الملف terraform.tfstate موجود، لكن قائمة موارده فارغة. ويجيب state show بـ No instance found for the given address! : العنوان صحيح، لكن لم يعد يقابله شيء، ويحيلك Terraform إلى state list. هذا هو مخرجك المطلوب الثاني : المخرجات الفارغة لـ terraform state list.

الخطوة 10 — سرد المجلد بعد ذلك

Windows (PowerShell) :

powershell
Get-ChildItem -Force

Linux وmacOS وWSL 2 وGit Bash :

bash
ls -la
text
total 17
drwxr-xr-x 1 rehou 197609    0 Sep 15 14:57 .
drwxr-xr-x 1 rehou 197609    0 Sep 15 14:57 ..
drwxr-xr-x 1 rehou 197609    0 Sep 15 14:57 .terraform
-rw-r--r-- 1 rehou 197609 1228 Sep 15 14:57 .terraform.lock.hcl
-rw-r--r-- 1 rehou 197609  130 Sep 15 14:57 main.tf
-rw-r--r-- 1 rehou 197609  181 Sep 15 14:57 terraform.tfstate
-rw-r--r-- 1 rehou 197609 1653 Sep 15 14:57 terraform.tfstate.backup

(سرد ls -la من جهاز الدورة ؛ يعرض Get-ChildItem -Force الأسماء الخمسة نفسها : .terraform، .terraform.lock.hcl، main.tf، terraform.tfstate، terraform.tfstate.backup.)

ما يطلبه الأمر : « أرِني المجلد كله، بما في ذلك الملفات المخفية. »

ما يجب النظر إليه : لم يعد bonjour.txt موجودًا. main.tf سليم : تدمير الموارد لا يمسّ الشيفرة أبدًا. terraform.tfstate ما زال موجودًا لكنه ضئيل (181 بايتًا)، وظهر terraform.tfstate.backup : نسخة السجل من قبل destroy، التي يحتفظ بها Terraform احتياطًا. يبقى أيضًا .terraform/ و.terraform.lock.hcl : إذا أعدت تشغيل apply، فلا حاجة لإعادة init.

افتح state لتراه فارغًا، دون تعديله (Get-Content .\terraform.tfstate أو cat terraform.tfstate) :

json
{
  "version": 4,
  "terraform_version": "1.12.2",
  "serial": 6,
  "lineage": "69fb219e-a88c-a97f-5aed-a33e7c34ff69",
  "outputs": {},
  "resources": [],
  "check_results": null
}

"resources": [] : لا شيء. يعدّ "serial" عمليات الكتابة في state (ست هنا : apply مرتَين في الورشة 1، ثم الإصلاح، والاستبدال والتدمير) ؛ و"lineage" هو معرّف هذا state، مختلف عندك.

التحقق النهائي

اصعد إلى جذر العُدّة وشغّل العدّاد :

Windows (PowerShell) :

powershell
cd ..\..
.\labo.ps1 etat

Linux وmacOS وWSL 2 وGit Bash :

bash
cd ../..
./labo.sh etat
text
travail atelier-1 : aucune ressource
Ressources encore gérées : 0 (0 attendu à la fin d'une séance).

الإجابة المنتظرة : aucune ressource (لا موارد) وRessources encore gérées : 0 (الموارد التي ما زالت مُدارة : 0). هذه نهاية الجلسة النظيفة التي سيطلبها كل مشروع في الدورة، عندما تكلّف الموارد مالًا.

  • حذفت bonjour.txt يدويًا ورأيت plan يقترح will be created دون أن تتغيّر الشيفرة : انحراف، مكشوف عند Refreshing state....
  • أعاد apply إنشاء الملف بـ نفس id.
  • غيّرت content وقرأت المؤشرات الثلاثة للاستبدال : must be replaced، # forces replacement، Plan: 1 to add, 0 to change, 1 to destroy.
  • عرض apply السطر Destroying... ثم Creating...، وResources: 1 added, 0 changed, 1 destroyed. ؛ وتغيّر id.
  • طلب destroy كلمة yes مع There is no undo. وأجاب Destroy complete! Resources: 1 destroyed.
  • لا يُرجع state list شيئًا ؛ ويُرجع state show القيمة No instance found for the given address! ؛ ويحتوي terraform.tfstate على "resources": [].
  • يُرجع etat القيمة Ressources encore gérées : 0.
  • احتفظت بخطة الخطوة 5 والمخرجات الفارغة للخطوة 9 كمخرجات مطلوبة.

إذا تعطّل شيء

عرض الحالات الشائعة
  • في الخطوة 1، يجيب state list بـ No state file was found! → لست في travail/atelier-1، أو لم تُنجَز الورشة 1 حتى apply. تحقق من المجلد (يجب أن يعرض Get-ChildItem -Force أو ls -la الملف terraform.tfstate)، وإلا أعد الورشة 1.
  • في الخطوة 1، لا يجيب state list بشيء → دُمّر المورد أصلًا (destroy في نهاية الورشة 1). أعد تشغيل terraform apply، yes، ثم استأنف من الخطوة 2.
  • في الخطوة 3، تقول الخطة No changes. → لم يُحذف الملف (خطأ مطبعي في Remove-Item أو rm، أو مجلد خاطئ). تحقق بـ Get-ChildItem أو ls، واحذفه، وأعد تشغيل plan.
  • في الخطوة 5، تقول الخطة No changes. → لم يُحفظ main.tf بعد التعديل (VS Code : نقطة بيضاء في علامة التبويب). Ctrl+S ثم أعد التشغيل.
  • في الخطوة 5، Error: Unterminated template string → سقطت علامة الاقتباس الختامية للقيمة الجديدة content أثناء التحرير. أعدها.
  • في الخطوة 5، السطر الموسوم # forces replacement ليس content → عدّلت وسيطًا آخر في الوقت نفسه (مثلًا file_permission = "0644"). بالنسبة لـ local_file، يفرض هذا أيضًا الاستبدال (مُتحقَّق منه : ~ file_permission = "0777" -> "0644" # forces replacement). أعد الملف كما في الخطوة 5، يجب أن يتغيّر سطر content فقط.
  • Apply cancelled. → كُتب شيء غير yes. أعد التشغيل، واكتب yes كاملة.
  • في الخطوة 8، يقول destroy : No changes. No objects need to be destroyed. ثم Destroy complete! Resources: 0 destroyed. → لم يبقَ شيء أصلًا في state (Either you have not created any objects yet or the existing objects were already deleted outside of Terraform.). انتقل إلى الخطوة 9.
  • بعد destroy، تعتقد أن state لم يُنظَّف لأن terraform.tfstate ما زال موجودًا → هذا طبيعي. افتحه : "resources": []. يبقى الملف، فارغًا، مع .backup بجانبه.
  • يجيب etat بـ Ressources encore gérées : 1 → أُلغي destroy أو نُفّذ في مجلد آخر. عُد إلى travail/atelier-1، terraform destroy، yes، وأعد تشغيل etat.