📜 शाळेच्या पद्धतीने Terraform शिका

Infrastructure as Code, शाळेच्या इमारतीच्या आराखड्यांसारखे शिकवलेले: बांधकाम कार्यालय हाताने खोल्या बांधणे थांबवते आणि लिखित आराखडे ठेवते, आणि कंत्राटदार (Terraform किंवा OpenTofu) ते जागेच्या नोंदवहीशी (state) आणि खऱ्या campus शी तुलना करतो, एक plan दाखवतो आणि फक्त फरक बांधतो. प्रत्येक धडा म्हणजे एक शाळेची गोष्ट, त्यासोबत काढलेली आकृती आणि एक lab — आणि कंत्राटदार repo मध्येच आहे: शुद्ध Python मधील एका बनावट campus वर चालणारे एक छोटे, deterministic, Terraform सारखे engine (iac/, शून्य dependencies, cloud account नको).

📜 git मधील आराखडे🧱 providers · schemas📋 + ~ -/+ -🔁 count · for_each📒 state🕸️ graph🧩 modules🔒 locking🌪️ drift · import · moved🏘️ workspaces🧪 policy · cost · tests🚀 OIDC pipelines

📐 भाग 1 — आराखडे (1–4)

  • clicks विरुद्ध आराखडे 📜
  • आराखड्यांत काय लिहिता येते 🧱
  • फक्त फरक बांधा 📋
  • एक design, अनेक खोल्या 🔁

📒 भाग 2 — नोंदवही आणि कंत्राटदार (5–8)

  • जागेची नोंदवही 📒
  • फाटकांआधी खोल्या 🕸️
  • एका wing चे design, दोनदा 🧩
  • एका वेळी एकच लिहिणारा 🔒

🏘️ भाग 3 — अनेक जागा, सुरक्षितपणे (9–12)

  • कोणीतरी click केले 🌪️
  • dev आणि prod 🏘️
  • निरीक्षक plan वाचतात 🧪
  • conveyor belt 🚀
# the 60-second wow — one set of plans, one register, one contractor:
git clone https://github.com/BaluRaut/learn-terraform-school.git && cd learn-terraform-school
python3 iac/demo.py               # 12 lessons: plans, diffs, registers, locks, drift, pipelines
python3 iac/test_iac.py           # 12 checks across the lessons

तुम्हाला काय दिसायला हवे (छाटलेले — यश असे दिसते):

═══ why ═══
── the works office builds the same campus 3 times BY HAND (8 fields per site, 10% chance of a slip per field)
   dev      8 fields typed · 5 objects · slips: none
   staging  8 fields typed · 5 objects · slips: none
   prod     8 fields typed · 5 objects · slips: floor typed 20 instead of 2
   do the 3 hand-built sites match? False
── the same campus from WRITTEN PLANS (a config), applied to 3 empty sites
   each site: Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
   do the 3 plan-built sites match? True
── apply the same plans to the dev site again → No changes. Your infrastructure matches the configuration.
   plans are text: reviewed in a pull request, kept in git, repeatable — clicks are none of these

═══ resources ═══
── the plans, in HCL (the lab keeps the same thing as a Python dict):
   resource "school_room" "lab" {
     name = "chem-lab"
     floor = 2
     seats = 30
   }
── the provider's schema for school_room (what the plans may say, and what the campus fills in):
   name   required · string
   floor  default 1 · number · forces a new room if changed
   seats  default 30 · number
   tags   default {} · map
   id     computed · string
── apply → Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
   the provider called the campus API: ['POST /rooms → room-01']
   school_room.lab is now id room-01 · attributes {'name': 'chem-lab', 'floor': 2, 'seats': 30, 'tags': {}, 'id': 'room-01'}

═══ plan ═══
── version 1 of the plans: lab, art room, main gate → Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
── version 2: lab seats 30 → 40 · art room moves to floor 3 · the gate is removed · a library is added
     ~ school_room.lab  seats: 30 → 40
   -/+ school_room.art  floor: 1 → 3  # forces replacement
     + school_room.library (create)
     - school_gate.main (destroy)
   Plan: 2 to add, 1 to change, 2 to destroy.
── apply → Apply complete! Resources: 2 added, 1 changed, 2 destroyed.
   the art room is a NEW object: room-02 → room-03 · the lab kept its id room-01
   ~ update in place keeps the object · -/+ replace destroys it and builds a new one (floor is ForceNew)

═══ variables ═══
── defaults (env=dev, seats=30) → Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
   output lab_name = "dev-school-lab"
   output locker_ids = ["locker-01", "locker-02", "locker-03"]
── -var env=prod -var seats=40 → ~ school_room.lab  name: 'dev-school-lab' → 'prod-school-lab' · seats: 30 → 40
── count: remove 'b' from [a, b, c] → ~ school_locker.row[1]  label: 'b' → 'c' · - school_locker.row[2] (destroy) → Plan: 0 to add, 1 to change, 1 to destroy.
── for_each over [a, b, c] makes school_locker.row["a"], school_locker.row["b"], school_locker.row["c"]
── for_each: remove 'b' → - school_locker.row["b"] (destroy) → Plan: 0 to add, 0 to change, 1 to destroy.
   count keys by POSITION, so removing the middle item shifts the rest · for_each keys by NAME

═══ state ═══
── apply the campus → Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
   output lab_id = "room-01"
   output code_a = <sensitive>
── the register (state): version 4 · serial 1 · lineage campus-3f9a · 5 resources
   {"school_locker.a": {"type": "school_locker", "id": "locker-01", "attrs": {"room_id": "room-01", "label": "a", "size": "m", "id": "locker-01", "combination": "6872"}, "deps": ["school_room.lab"]}}
   search the state for 'combination' → ['school_locker.a: 6872', 'school_locker.b: 4434', 'school_locker.c: 4123']
   sensitive = true hides a value in plan and output — the state still holds it in plain text
── the register is lost; plan with an empty one → Plan: 5 to add, 0 to change, 0 to destroy.
   after apply the campus has 2 rooms named ['chem-lab'] and 10 objects — duplicates, not the same campus

═══ graph ═══
── edges (a → b means a must exist first):
   school_room.lab → school_gate.main
   school_room.lab → school_locker.row[0]
   school_room.library → school_gate.back
   school_gate.main → school_gate.back   (explicit depends_on)
   school_room.lab → school_locker.row[1..3]   (same as row[0])
── parallelism 10: 3 steps for 8 resources → [2, 5, 1] per step
   step 1: school_room.lab, school_room.library
   step 2: school_gate.main, school_locker.row[0], school_locker.row[1], school_locker.row[2], school_locker.row[3]
   step 3: school_gate.back
── parallelism  2: 4 steps for 8 resources → [2, 2, 2, 2] per step
── parallelism  1: 8 steps for 8 resources
── destroy runs the graph backwards:
   step 1: school_locker.row[0], school_locker.row[1], school_locker.row[2], school_locker.row[3], school_gate.back
   step 2: school_room.library, school_gate.main
   step 3: school_room.lab
── a gate that needs a locker that needs the gate → Error: Cycle: school_gate.g, school_locker.l

═══ modules ═══
── one module (modules/wing: a hall, a gate, N lockers), called twice:
   module "east" { source = "./modules/wing", wing = "east" }
   module "west" { source = "./modules/wing", wing = "west", lockers = 3 }
   output "east_gate" { value = module.east.gate_id }
   output "west_hall" { value = module.west.hall_id }
   Plan: 9 to add, 0 to change, 0 to destroy.
   module.east: school_room.this, school_gate.this, school_locker.row[0], school_locker.row[1]
   module.west: school_room.this, school_gate.this, school_locker.row[0], school_locker.row[1], school_locker.row[2]
── apply → Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
   output east_gate = "gate-01"
   output west_hall = "room-02"
── west asks for 4 lockers → + module.west.school_locker.row[3] (create) → Plan: 1 to add, 0 to change, 0 to destroy.
   the module is written once; each call gets its own inputs, addresses and outputs

═══ locking ═══
── NO lock · the register holds the lab (serial 1) · Katrina adds a gym, Dipika adds a library, at the same time
   both read serial 1 · Katrina: Plan: 1 to add, 0 to change, 0 to destroy. · Dipika: Plan: 1 to add, 0 to change, 0 to destroy.
   both wrote serial 2; Dipika wrote last → the register knows ['school_room.lab', 'school_room.library']
   the campus has 3 rooms, the register knows 2 → orphan: ['gym'] — built, paid for, managed by nobody
── WITH lock · the register holds the lab (serial 1) · Katrina adds a gym, Dipika adds a library, at the same time
   Katrina takes the lock (lock-0001) and plans + applies
   Dipika → Error acquiring the state lock · Lock Info: ID lock-0001 · Path campus.tfstate · Operation OperationTypeApply · Who katrina@works-office
   Katrina is done (serial 2); Dipika gets lock-0002, reads the NEW register → Plan: 1 to add, 0 to change, 1 to destroy.  ← her branch lacks the gym
   she pulls Katrina's change first → Plan: 1 to add, 0 to change, 0 to destroy.
   Apply complete! Resources: 1 added, 0 changed, 0 destroyed. serial 3 · campus rooms 3 = register 3
   one register in one shared place, one writer at a time

═══ drift ═══
── Dipika clicks in the console: room-01 seats 30 → 45 (no plans changed, no register changed)
   plan -refresh-only → ['school_room.lab has changed outside of Terraform: seats 30 → 45']
   plan → ~ school_room.lab  seats: 45 → 30 → Plan: 0 to add, 1 to change, 0 to destroy.
   with lifecycle ignore_changes = [seats] → No changes. Your infrastructure matches the configuration.
   apply the plan → Apply complete! Resources: 0 added, 1 changed, 0 destroyed. · seats are 30 again
── someone built a back gate by hand: gate-02 — the register has never heard of it
   plan with the gate in the plans but no import → Plan: 1 to add, 0 to change, 0 to destroy.  (a second gate)
   add an import block → ← school_gate.back will be imported (id gate-02)
   Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
   Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
── rename school_room.lab → school_room.science in the plans
   without a moved block → Plan: 3 to add, 0 to change, 3 to destroy.  (the lab AND both gates would be rebuilt)
   with moved { from = school_room.lab, to = school_room.science } → school_room.lab has moved to school_room.science · Plan: 0 to add, 0 to change, 0 to destroy.

═══ environments ═══
── one set of plans, two workspaces, one .tfvars file each
   workspace dev  + dev.tfvars {'seats': 10, 'lockers': 1} → Apply complete! Resources: 2 added, 0 changed, 0 destroyed. → register at env:/dev/campus.tfstate
   workspace prod + prod.tfvars {'seats': 40, 'lockers': 3} → Apply complete! Resources: 4 added, 0 changed, 0 destroyed. → register at env:/prod/campus.tfstate
   the backend now holds ['env:/dev/campus.tfstate', 'env:/prod/campus.tfstate'] · the campus has 6 objects
── Katrina forgets `workspace select dev` and plans with dev.tfvars while prod is selected:
     ~ school_room.lab  seats: 40 → 10
     - school_locker.row[1] (destroy)
     - school_locker.row[2] (destroy)
   Plan: 0 to add, 1 to change, 2 to destroy.  ← prod shrinks to dev's size
── three ways to keep environments apart:
   workspaces   same code, same backend, a state per workspace · quick, but one wrong select hits prod
   directories  envs/dev and envs/prod call the same modules, each with its own backend key · clear, a little copying
   accounts     separate cloud accounts + separate state + separate CI roles · the strongest wall between dev and prod

═══ policy ═══
── validate (no campus needed) on a broken config:
   school_room.gym: Inappropriate value for attribute "seats": a number is required.
   school_room.gym: An argument named "colour" is not expected here.
   school_room.gym: The argument "name" is required, but no definition was found.
   school_gate.g: Reference to undeclared resource "school_room.pool".
── plan → Plan: 5 to add, 0 to change, 0 to destroy. · policy check (dev):
   DENY school_room.gym: every room needs an owner tag (tags has no 'owner')
   DENY school_gate.night: gates must close at night (open_hours = '00-24')
   DENY school_locker.big: no xl lockers outside prod (size = 'xl' in dev)
── cost estimate: ₹0/month → ₹2830/month (+2830) — made-up prices, the shape of an Infracost comment
── tests (like `terraform test` with command = plan):
     run "the lab has 30 seats"... pass
     run "the lab gets 2 lockers"... pass
     run "gates close at night"... fail
    Error: Test assertion failed — a gate is open 00-24
   Failure! 2 passed, 1 failed.
   validate checks the plans' SHAPE · tests check what they MEAN · policy checks what is ALLOWED · cost checks what it COSTS

═══ pipeline ═══
── who may do what: the CI job gets a short-lived OIDC token, no stored cloud keys
   pull_request sub=repo:school/campus-infra:pull_request
      → campus-plan: granted, read-only (plan), session 3600 s
      → campus-apply: AccessDenied — sub 'repo:school/campus-infra:pull_request' does not match
   push         sub=repo:school/campus-infra:ref:refs/heads/main
      → campus-plan: granted, read-only (plan), session 3600 s
      → campus-apply: granted, read-write (apply), session 3600 s
   PR #42: campus-plan: granted, read-only (plan), session 3600 s
   PR #42: validate → Success! The configuration is valid.
   PR #42: plan (state serial 1) → Plan: 1 to add, 0 to change, 0 to destroy.
   PR #42: policy → 0 denied
   PR #42: cost → ₹1200/month → ₹2400/month (+1200)
   PR #42: comment posted with the plan · ready for review
   PR #43: campus-plan: granted, read-only (plan), session 3600 s
   PR #43: validate → Success! The configuration is valid.
   PR #43: plan (state serial 1) → Plan: 1 to add, 0 to change, 0 to destroy.
   PR #43: policy → 0 denied
   PR #43: cost → ₹1200/month → ₹1500/month (+300)
   PR #43: comment posted with the plan · ready for review
   merge #43: campus-apply: granted, read-write (apply), session 3600 s
   merge #43: Apply complete! Resources: 1 added, 0 changed, 0 destroyed. (state serial 2)
   merge #42: campus-apply: granted, read-write (apply), session 3600 s
   merge #42: Saved plan is stale: the state was changed by another operation after the plan was created.
   merge #42: re-plan (state serial 2) → Plan: 1 to add, 0 to change, 1 to destroy.
   merge #42: the new plan is NOT the plan that was reviewed → stop, nothing applied
   PR #42 (rebased on main): plan (state serial 2) → Plan: 1 to add, 0 to change, 0 to destroy.
   merge #42: campus-apply: granted, read-write (apply), session 3600 s
   merge #42: Apply complete! Resources: 1 added, 0 changed, 0 destroyed. (state serial 3)
── main = campus: register serial 3 · 3 resources · campus 3 objects
── the whole picture: plans in git → validate, test, policy, cost → plan on the PR → review → apply on merge with OIDC
   → one locked remote register → refresh finds drift → import and moved keep the register honest → the same plans for every site

✅ done — the campus matches the plans
🎒 धडा 01 आधी: तुम्हाला फक्त Python 3 हवे — दुसरे काही नको. हा lab म्हणजे बनावट campus वर (school_room, school_gate, school_locker) Terraform च्या workflow चे एक deterministic शिकवणी model आहे, खुद्द Terraform नाही. खऱ्या terraform commands फक्त खऱ्या account वर असे लिहिलेल्या blocks मध्ये येतात (Terraform ≥ 1.5; terraform test साठी ≥ 1.6). हे कुठे बसते: AWS शाळा हा तो campus आहे जो हे आराखडे सहसा बांधतात; CI/CD शाळा ते apply करणारी pipeline चालवते.

🗺️ संपूर्ण चित्र — एक आकृती, पूर्ण कोर्स

संपूर्ण कोर्स एका कॅनव्हासवर. 4K आवृत्तीसाठी क्लिक करा.

The big picture: the plans (why IaC, resources and providers, plan and apply, variables and loops), the register and the contractor (state, the dependency graph, modules, remote state and locking) and many sites safely (drift and import, environments, testing and policy, IaC in CI/CD)

📐 भाग 1 — आराखडे (धडे 1–4)

एक git branch = एक कल्पना; branch 04 मध्ये धडे 01–04 आहेत. iac/ चा प्रत्येक run सारखाच असतो — randomness seeded आहे.

1

📜 infrastructure as code का

Clicks विरुद्ध लिखित आराखडे — आराखड्यांवरून बांधलेला campus पुन्हा बांधता, review करता आणि नव्याने उभारता का येतो.lesson-01-why-iacधडा वाचा →आकृती पहा ↗
2

🧱 Resources आणि providers

Resources, providers आणि schemas — आराखड्यांत काय लिहिता येते आणि campus काय भरतो.lesson-02-resources-providersधडा वाचा →आकृती पहा ↗
3

📋 Plan आणि apply

Diff: create, जागीच update, replace, destroy — आणि नवीन object बनवायला भाग पाडणारे arguments.lesson-03-plan-applyधडा वाचा →आकृती पहा ↗
4

🔁 Variables, outputs आणि loops

Variables, locals, outputs, count आणि for_each — आणि मधली item काढणे का महत्त्वाचे ठरते.lesson-04-variables-loopsधडा वाचा →आकृती पहा ↗

📒 भाग 2 — नोंदवही आणि कंत्राटदार (धडे 5–8)

कंत्राटदार आपण काय बांधले ते कसे लक्षात ठेवतो, कामाचा क्रम कसा ठरवतो, designs पुन्हा कसे वापरतो आणि एकच नोंदवही सुरक्षितपणे कशी वाटून घेतो.

5

📒 State

जागेची नोंदवही: कोणता address कोणता खरा object आहे — आणि त्यात secrets का असतात.lesson-05-stateधडा वाचा →आकृती पहा ↗
6

🕸️ Dependency graph

फाटकांआधी खोल्या: implicit आणि explicit क्रम, parallel पायऱ्या, cycles.lesson-06-dependency-graphधडा वाचा →आकृती पहा ↗
7

🧩 Modules

एका wing चे design, दोनदा बांधलेले: inputs आणि outputs असलेले modules.lesson-07-modulesधडा वाचा →आकृती पहा ↗
8

🔒 Remote state आणि locking

एकाच सामायिक जागी एक नोंदवही, एका वेळी एकच लिहिणारा.lesson-08-remote-state-lockingधडा वाचा →आकृती पहा ↗

🏘️ भाग 3 — अनेक जागा, सुरक्षितपणे (धडे 9–12)

Drift, environments, checks आणि pipelines: आराखडे खरोखर, अनेक जागांसाठी, एका team सोबत चालवणे.

9

🌪️ Drift आणि import

कोणीतरी console मध्ये click केले: refresh, drift, ignore_changes, import आणि moved blocks.lesson-09-drift-importधडा वाचा →आकृती पहा ↗
10

🏘️ Environments

त्याच आराखड्यांवरून dev आणि prod: workspaces विरुद्ध directories विरुद्ध वेगळे accounts.lesson-10-environmentsधडा वाचा →आकृती पहा ↗
11

🧪 Testing आणि policy

Validate, tests, policy आणि cost — काहीही बांधण्याआधी plan वाचणारे निरीक्षक.lesson-11-testing-policyधडा वाचा →आकृती पहा ↗
12

🚀 CI/CD मधील IaC आणि संपूर्ण चित्र

Pull request वर plan, merge वर apply, keys ऐवजी OIDC — आणि संपूर्ण चित्र.lesson-12-iac-cicdधडा वाचा →आकृती पहा ↗
🗣️ हे मोठ्याने समजावून सांगा — धडा 12 नंतर: (1) आराखड्यावरून बांधलेली जागा पुन्हा बांधता येते, पण हाताने बांधलेली का नाही? (2) ForceNew argument plan वर काय परिणाम करतो? (3) मधली item काढल्याने count सोबत त्रास का होतो, पण for_each सोबत का नाही? (4) State कशाचे mapping ठेवते, आणि ते secret का आहे? (5) Apply चा क्रम कोण ठरवते? (6) दोन लिहिणारे आणि lock नसेल तर काय बिघडते? (7) import आणि moved blocks तुम्हाला कशापासून वाचवतात? (8) CLI workspaces म्हणजे dev आणि prod मधली कमकुवत भिंत का आहेत? (9) CI ने OIDC का वापरावे, आणि apply केलेल्या plan ची review केलेल्या plan शी तुलना का करावी?
🎓 याच शाळेतून: AWS · CI/CD · IAM · Argo CD — तेच उपमांचे विश्व, तीच branch-दर-branch पद्धत.

📐 धड्यांच्या आकृत्या — क्रमांक अनुसरा

प्रत्येक धडा एका क्रमांकित बॉक्स-आणि-बाण आकृतीत — स्वतंत्र पानावरही.

1 📜 infrastructure as code का

Clicks विरुद्ध लिखित आराखडे — आराखड्यांवरून बांधलेला campus पुन्हा बांधता, review करता आणि नव्याने उभारता का येतो.

🧒 सोप्या शब्दांत

शाळेला तीन गावांत एकसारखी science wing हवी आहे. कतरिना प्रत्येक wing हाताने बांधते आणि दर वेळी 8 गोष्टी type करते. तिसऱ्या site वर ती floor 2 ऐवजी 20 type करते. आता wings एकसारख्या नाहीत. म्हणून दीपिका एकदाच आराखडा लिहून ठेवते. Contractor आराखड्यावरून बांधतो, आणि तिन्ही wings जुळतात. तो पुन्हा आला की म्हणतो: काहीच करायचे नाही.

📖 नवे शब्दinfrastructure — तुमचे programs ज्यात राहतात त्या खोल्या, gates आणि lockers; खऱ्या आयुष्यात servers आणि networksinfrastructure as code — click करण्याऐवजी campus text files मध्ये लिहून ठेवणेdeclarative — काय असायला हवे ते तुम्ही सांगता, आणि पायऱ्या tool ठरवतेidempotent — काहीच वेगळे नसेल तर पुन्हा चालवल्यावर काहीच बदलत नाही
1✋ हाताने — कतरिना प्रत्येक जागेसाठी 8 fields टाइप करतेcampus console1. खोलीchem-lab2. मजला23. आसने304. फाटकmain-gate5. वेळ08-186. lockera7. lockerb8. lockercKatrina8 fields × 3 जागाप्रत्येक field ला 10% चूकdev8 टाइप केले · 5 objectsचुका: एकही नाहीstaging8 टाइप केले · 5 objectsचुका: एकही नाहीprodमजला 208 टाइप केले · 5 objectsचूक: मजला 20, 2 नाहीहाताने बांधलेल्या 3 जागा जुळतात का? False2📜 लिखित आराखडे — एक config, 3 वेळा apply केलेलाcampus.tf (git मध्ये)resource "school_room" "lab" { name = "chem-lab" floor = 2 seats = 30}resource "school_gate" "main" { room_id = school_room.lab.id}resource "school_locker" … × 3कंत्राटदारterraform applydevApply complete!5 added, 0 changedstagingApply complete!5 added, 0 changedprodApply complete!5 added, 0 changedआराखड्यावरून बांधलेल्या 3 जागा जुळतात का? True3🔁 कंत्राटदार त्याच आराखड्यांसह पुन्हा dev ला भेट देतो$ terraform planNo changes. Your infrastructure matches the configuration.आराखडे म्हणजे text, म्हणून ते:✍️ pull request मध्ये review होतात🗂️ git मध्ये ठेवले जातात🔁 पुन्हा करता येतातclicks: एकही नाहीयांपैकी
⏪ आधी

एक clerk प्रत्येक site web console मध्ये click करून बांधत असे: प्रत्येक site ला 8 fields हाताने, आणि का ते कुठेच लिहिलेले नाही.

💡 काय

Infrastructure as code: works office campus चा आराखडा git मध्ये लिहून ठेवते, आणि contractor त्यावरून बांधकाम करतो.

⚙️ कसे

हाताने बांधताना prod ला floor 2 ऐवजी 20 पडला, म्हणून 3 sites जुळत नाहीत. आराखड्यातून: प्रत्येकी 5 added, आणि त्या जुळतात.

🎯 का

आराखडा pull request मध्ये तपासता येतो, git मध्ये ठेवता येतो आणि पुन्हा वापरता येतो. dev वर दुसरे apply 'No changes.' म्हणते.

🚀 पुढे

पुढचा धडा आराखडा उघडतो: एका resource block मध्ये काय लिहिता येते, आणि provider व campus काय भरतात.

🧪 इथे करून पाहा — 3 जागा हाताने विरुद्ध आराखड्यांवरून बांधा — चुकीची शक्यता आणि दिवस बदला
105

पूर्ण धडा 01 वाचा →

2 🧱 Resources आणि providers

Resources, providers आणि schemas — आराखड्यांत काय लिहिता येते आणि campus काय भरतो.

🧒 सोप्या शब्दांत

कतरिना आराखड्यात एक ओळ लिहिते: chem-lab नावाची खोली, floor 2 वर, 30 seats. Campus ओळखणारा एक मदतनीस ती वाचतो. त्याच्याकडे खोल्यांचे नियम-पुस्तक आहे. नियम सांगतो की खोलीला नाव हवेच. Campus खोली बांधतो आणि तिला एक नंबर देतो: room-01. कतरिना तो नंबर स्वतः कधीच ठरवत नाही.

📖 नवे शब्दresource — बांधायची एक गोष्ट, जसे एक खोली किंवा एक gateprovider — आराखड्याचे एका cloud साठी calls मध्ये रूपांतर करणारा मदतनीस pluginschema — नियम-पुस्तक: कोणत्या गोष्टी चालतात, लागतातच किंवा नंतर भरल्या जातातcomputed — campus भरतो ते मूल्य, जसे id room-01
1🧱 आराखडे सांगतात काय; provider ला माहीत असते कसे; बाकीचे campus भरतोआराखडे (HCL)resource "school_room" "lab" { name = "chem-lab" floor = 2 seats = 30}type "school_room" · name "lab"address: school_room.lab🔌 provider (एक plugin) — school_room साठी त्याचे schemaargनियमप्रकारचिठ्ठीnameआवश्यकstringfloordefault 1numberनवीन खोली बनवायला भाग पाडतेजागाdefault 30numbertagsdefault {}mapidcomputedstringcampus ते भरतोvalidate आराखडे या schema शी तपासतोकाहीही बांधण्याआधीPOST/rooms🏫 campus (cloud)chem-labid = room-01id campus निवडतो —आराखडे कधीच नाहीPOST /rooms → room-01Apply complete! Resources: 1 added, 0 changed, 0 destroyed.provider ने campus API एकदा call केली2📒 नंतर कंत्राटदार काय लिहून ठेवतोschool_room.labname'chem-lab'floor2जागा30tags{}id'room-01'← attributes, जसेcampus सांगतो तसेआराखड्यांनी ठरवलेलेschema ने जोडलेला defaultcampus ने computed केलेले
⏪ आधी

प्रत्येक console form चे fields आणि नियम वेगळे होते; 'create' दाबण्याआधी खोलीची settings कोणी तपासू शकत नसे.

💡 काय

Resource म्हणजे बांधायची एक गोष्ट, जसे school_room.lab. Provider plugin ला त्याचे schema आणि campus API माहीत असते.

⚙️ कसे

Lab साठी chem-lab, floor 2, 30 seats मागितले. Provider POST /rooms करतो आणि campus id room-01 देतो.

🎯 का

Schema सांगते: name required आहे, floor चा default 1 आणि बदलला तर नवी खोली, आणि id computed आहे: आराखडा तो कधीच ठरवत नाही.

🚀 पुढे

पुढच्या धड्यात आराखडा बदलतो आणि diff वाचतो: कोणत्या ओळी जागीच update होतात आणि कोणत्या पुन्हा बांधल्या जातात.

🧪 इथे करून पाहा — एक school_room लिहा — provider चे schema ते तपासते, बाकीचे campus भरतो
2

पूर्ण धडा 02 वाचा →

3 📋 Plan आणि apply

Diff: create, जागीच update, replace, destroy — आणि नवीन object बनवायला भाग पाडणारे arguments.

🧒 सोप्या शब्दांत

ऐश्वर्या आराखडा बदलते. Lab ला 30 ऐवजी 40 seats. Art room floor 3 वर जाते. Gate जाते, आणि library येते. बांधण्याआधी contractor एक यादी दाखवतो. अधिक म्हणजे बांधा, नागमोडी खूण म्हणजे जागीच दुरुस्त करा, आणि वजा म्हणजे पाडा. खोली दुसऱ्या floor वर नेणे म्हणजे अगदी नवी खोली. ऐश्वर्या आधी यादी वाचते, मग हो म्हणते.

📖 नवे शब्दplan — contractor करणार असलेल्या बदलांची यादी, काहीही होण्याआधी दाखवलेलीapply — खऱ्या campus वर plan प्रत्यक्ष अमलात आणणेupdate in place — तीच खोली दुरुस्त करणे, जसे जास्त seats; id room-01 तसाच राहतोreplace — खोली पाडून नव्या id सह नवी खोली बांधणे
1📋 आराखड्याची version 2 विरुद्ध version 1 ने बांधलेला campusआत्ताचा campus (version 1)lab · 30 जागाroom-01art · मजला 1room-02main-gategate-013 objects$ terraform plan~school_room.labजागा: 30 → 40-/+school_room.artमजला: 1 → 3# forces replacement+school_room.library(create)-school_gate.main(destroy)Plan: 2 to add, 1 to change, 2 to destroy.Aishwaryaसगळं वाचते,मग हो म्हणतेapplyनंतरlab: room-01(तोच object)art: room-03(एक नवीन object)library: room-04main-gate: नाहीसे2 जोडले · 1 बदलला· 2 पाडले2🔧 plan एखाद्या object ला करू शकतो अशा चार गोष्टी~जागीच update-/+replace+create-destroylabroom-01labroom-0130 जागा40 जागाPATCH room-01 — objectआणि त्याचा id तसाच राहतोजागांची संख्या जागीच बदलू शकतेart · मजला 1room-02art · मजला 3room-03DELETE room-02, मगPOST /rooms → room-03floor ForceNew आहे: नवा idlibraryroom-04आराखड्यात आहे, पणनोंदवहीत नाही → बांधा60 जागा, नवा idmain-gategate-01नोंदवहीत आहे, पणआराखड्यात नाही → पाडाDELETE gate-01
⏪ आधी

बदल थेट campus वर केले जात; एखादा बदल खोली पाडेल का हे आधी कोणालाच कळत नसे.

💡 काय

Plan आराखडा, नोंदवही आणि campus यांची तुलना करतो: + create, ~ update, -/+ replace आणि - destroy.

⚙️ कसे

Version 2: lab seats 30 → 40 (~), art floor 1 → 3 (-/+), library (+), gate नाही (-). Plan: 2 to add, 1 to change, 2 to destroy.

🎯 का

Replace म्हणजे update नव्हे: art room नवी वस्तू झाली, room-02 → room-03, पण lab ने आपला id room-01 ठेवला.

🚀 पुढे

पुढचा धडा inputs, outputs आणि loops आणतो: एकाच block मधून अनेक lockers, count किंवा for_each ने ओळखलेले.

🧪 इथे करून पाहा — आराखड्याची version 2 बदला — + ~ -/+ - ओळी पाहा
4023

पूर्ण धडा 03 वाचा →

4 🔁 Variables, outputs आणि loops

Variables, locals, outputs, count आणि for_each — आणि मधली item काढणे का महत्त्वाचे ठरते.

🧒 सोप्या शब्दांत

Office ला तीन lockers हवे आहेत: a, b आणि c. तीन blocks लिहिण्याऐवजी दीपिका एक block आणि एक loop लिहिते. count मध्ये lockers ना 0, 1 आणि 2 म्हणतात. b काढला तर c जागा 1 वर सरकतो, म्हणून c च्या locker चे label बदलते. for_each मध्ये lockers ना नावाने ओळखतात. b काढला तर फक्त b जातो. बाकी काहीच हलत नाही.

📖 नवे शब्दvariable — आराखड्यातील एक रिकामी जागा जी तुम्ही भरता, जसे env = devoutput — बांधल्यानंतर आराखडा सांगतो ते मूल्य, जसे locker idcount — N प्रती बनवा, जागेनुसार 0, 1, 2 असे नंबरfor_each — प्रत्येक नावासाठी एक प्रत, त्याच नावाने ओळखलेली
1🔁 inputs आत, outputs बाहेर — dev आणि prod साठी तोच आराखडाvar.env = "dev"var.seats = 30var.labels = [a, b, c]locals { prefix = "${var.env}-school" }school_room "lab" { name = "${local.prefix}-lab" seats = var.seats }room-01output lab_name = "dev-school-lab"output locker_ids = ["locker-01", "locker-02", "locker-03"]-var env=prod -var seats=40 →~ name: 'prod-school-lab' · seats: 30 → 402🔢 count — lockers ची ओळख स्थानानुसार (POSITION)आधीb काढा[0]label a[1]label b[2]label c[0]label a[1]label c~ 'b' → 'c'[2]~school_locker.row[1]label: 'b' → 'c'-school_locker.row[2](destroy)Plan: 0 to add, 1 to change, 1 to destroy.3🏷️ for_each — lockers ची ओळख नावानुसार (NAME)आधीb काढा["a"]label a["b"]label b["c"]label c["a"]label a["b"]["c"]label c-school_locker.row["b"](destroy)Plan: 0 to add, 0 to change, 1 to destroy.count नंतरचा प्रत्येक locker एक जागा खाली सरकवतो · for_each फक्त तुम्ही काढलेल्या locker लाच हात लावतो
⏪ आधी

प्रत्येक locker साठी copy-paste केलेला block होता, आणि dev व prod चे आराखडे वेगळ्या files मध्ये हळूहळू वेगळे होत गेले.

💡 काय

Variables आराखड्यात मूल्ये देतात, locals नावे ठरवतात, outputs ids सांगतात, आणि count किंवा for_each अनेक प्रती बांधतात.

⚙️ कसे

Defaults मुळे lab_name dev-school-lab आणि 3 lockers. count ने b काढला: 1 to change, 1 to destroy. for_each ने: फक्त 1 to destroy.

🎯 का

count lockers ना जागेनुसार ओळखतो, म्हणून मधला काढला की बाकी सरकतात; for_each त्यांना नावाने ओळखतो.

🚀 पुढे

पुढचा धडा नोंदवहीच उघडतो: कोणता address कोणती खरी वस्तू आहे हे contractor कसे लक्षात ठेवतो.

🧪 इथे करून पाहा — एक locker काढा — count स्थानानुसार key करतो, for_each नावानुसार
30

पूर्ण धडा 04 वाचा →

5 📒 State

जागेची नोंदवही: कोणता address कोणता खरा object आहे — आणि त्यात secrets का असतात.

🧒 सोप्या शब्दांत

Works office एक नोंदवही ठेवते. प्रत्येक ओळ सांगते की आराखड्यातील कोणते नाव कोणती खरी वस्तू आहे: lab म्हणजे room-01. Contractor प्रत्येक plan आधी ती वाचतो. नोंदवहीत locker codes पण असतात, जसे 6872, साध्या अक्षरात. Screen वर code लपवला तरी नोंदवहीत तो लपत नाही. एके दिवशी नोंदवही हरवते. Contractor सगळे पुन्हा बांधतो, आणि आता दोन chem-labs आहेत.

📖 नवे शब्दstate — आराखड्यातील प्रत्येक नाव एका खऱ्या वस्तूशी जोडणारी नोंदवहीserial — नोंदवही लिहिली की दर वेळी वाढणारा countersensitive — screen वर लपवलेले, पण नोंदवहीत तरीही लिहिलेलेduplicate — नोंदवही हरवल्यामुळे चुकून बांधलेली दुसरी प्रत
1📒 नोंदवही प्रत्येक address ला एका खऱ्या object शी जोडतेcampus.tfstateschool_room.lab → room-01school_gate.main → gate-01school_locker.a → locker-01school_locker.b → locker-02school_locker.c → locker-03version 4 · serial 1 · lineage campus-3f9a5 resourcesकंत्राटदार प्रत्येक plan आधीही वाचतो आणि प्रत्येक applyनंतर ही लिहितोखरा campusroom-01gate-01locker-01locker-02locker-032🔐 sensitive ते लपवते — state लपवत नाहीterraform outputoutput lab_id = "room-01"output code_a = <sensitive>"school_locker.a": { "id": "locker-01", "room_id": "room-01", "label": "a", "size": "m", "combination": "6872"}state मध्ये 'combination' शोधा:6872 · 4434 · 41233🔥 नोंदवही हरवली — रिकाम्या नोंदवहीसह plancampus.tfstate (हरवली)तिला काहीच माहीत नाही$ terraform plan+× 5 (create)Plan: 5 to add, 0 to change, 0 to destroy.जुने objects अजूनही उभे आहेत —कंत्राटदाराला ते फक्त दिसत नाहीतapplyनंतरचा campus: 10 objectschem-labchem-labपहिले बांधकामDUPLICATE (दुसरे) बांधकाम
⏪ आधी

Contractor ला काहीच आठवत नसे: बांधकामानंतर 'आराखड्यातील lab' आणि campus वरील room-01 यांचा संबंध कुठेच नव्हता.

💡 काय

State म्हणजे site ची नोंदवही: version 4, serial 1, lineage campus-3f9a, 5 addresses आणि 5 खऱ्या वस्तूंची जोडणी.

⚙️ कसे

sensitive = true मुळे code_a <sensitive> दिसते, तरीही state मध्ये 6872, 4434 आणि 4123 साध्या अक्षरात असतात.

🎯 का

नोंदवही हरवली की plan 5 to add म्हणतो; apply नंतर chem-lab नावाच्या 2 खोल्या आणि 10 वस्तू, म्हणजे duplicates.

🚀 पुढे

पुढचा धडा विचारतो कोणत्या क्रमाने बांधायचे: gates आधी खोल्या, आणि एका वेळी किती.

🧪 इथे करून पाहा — apply करा, मग नोंदवही हरवा आणि पुन्हा apply करा

पूर्ण धडा 05 वाचा →

6 🕸️ Dependency graph

फाटकांआधी खोल्या: implicit आणि explicit क्रम, parallel पायऱ्या, cycles.

🧒 सोप्या शब्दांत

खोली नसताना तिचे gate लावता येत नाही. Contractor बाण काढतो: आधी खोली, मग gate. ज्यांच्यामध्ये बाण नाही त्या गोष्टी एकाच वेळी बांधता येतात. 10 जणांच्या crew ला आठ गोष्टींसाठी 3 steps लागतात. 1 जणाला 8 steps. पाडताना उलट: आधी lockers, शेवटी खोल्या. दोन गोष्टी एकमेकींची वाट पाहत असतील तर कोणीच सुरू करू शकत नाही.

📖 नवे शब्दdependency — आधी असायलाच हवी अशी गोष्ट, जसे gate आधी खोलीdepends_on — आराखड्यात दिसत नसेल तेव्हा हाताने जोडलेला बाणparallelism — crew एकाच वेळी किती गोष्टी बांधतेcycle — दोन गोष्टी एकमेकींची वाट पाहतात, म्हणून काहीच सुरू होत नाही
1🕸️ आधी rooms, मग gates — क्रम graph ठरवतोstep 1step 2step 3depends_onschool_room.labschool_room.libraryschool_gate.mainschool_locker.row[0]school_locker.row[1]school_locker.row[2]school_locker.row[3]school_gate.backroom_id = …lab.idथांबायला काहीच नाहीभरीव रेषा = reference (room_id = …id) · लाल तुटक रेषा = depends_on2⚙️ -parallelism = कामगारांच्या टोळीचा आकारparallelism 10 → 3 पायऱ्या [2, 5, 1]251parallelism 2 → 4 पायऱ्या [2, 2, 2, 2]2222parallelism 1 → 8 पायऱ्या11111111दर वेळी तेच 8 resources —मोठी टोळी फक्त तयार असलेलेresources शेजारी शेजारी चालवतेठिपका = बांधला जात असलेला एक resource3⏪ destroy तोच graph उलट्या दिशेने चालतोstep 1row[0..3]gate.backstep 2room.librarygate.mainstep 3room.lablockers आणि gates ज्या rooms चे आहेत, त्या rooms च्या आधी पाडले जातात4🔄 cycle — पहिली पायरीच नाहीschool_gate.gschool_locker.lफाटकाला locker हवा, आणिlocker ला फाटक हवेError: Cycle: school_gate.g,school_locker.l
⏪ आधी

बांधकाम करणारे file मधल्या क्रमाने checklist पाळत आणि gate त्याच्या खोलीच्या आधी येणार नाही अशी आशा करत.

💡 काय

room_id = school_room.lab.id सारखा reference graph मधील एक edge आहे; depends_on हाताने edge जोडतो.

⚙️ कसे

8 resources: parallelism 10 मध्ये 3 steps [2, 5, 1], parallelism 2 मध्ये 4 steps, parallelism 1 मध्ये 8 steps.

🎯 का

Destroy graph उलटा चालतो, आधी lockers, शेवटी lab; locker ला gate आणि gate ला locker हवा असेल तर Cycle error येतो.

🚀 पुढे

पुढचा धडा hall, gate आणि lockers एका wing च्या आराखड्यात बांधतो आणि तो दोनदा वापरतो.

🧪 इथे करून पाहा — कामगारांची संख्या, lockers आणि depends_on बदला — पायऱ्या मोजा
104

पूर्ण धडा 06 वाचा →

7 🧩 Modules

एका wing चे design, दोनदा बांधलेले: inputs आणि outputs असलेले modules.

🧒 सोप्या शब्दांत

शाळेला east wing आणि west wing हवी आहे. प्रत्येक wing मध्ये एक hall, एक gate आणि काही lockers आहेत. दीपिका एकच wing आराखडा काढते आणि तो दोनदा वापरते. East ला 2 lockers आणि west ला 3. एकूण 9 गोष्टी. West ने चौथा locker मागितला की फक्त west मध्ये एक locker वाढतो. East wing ला अजिबात धक्का लागत नाही.

📖 नवे शब्दmodule — पुन्हा वापरता येणारा आराखडा, जसे wing चे एक चित्रinput — module ला दिलेले मूल्य, जसे किती lockersmodule output — module परत देते ते मूल्य, जसे gate idaddress — एखाद्या गोष्टीचे पूर्ण नाव, जसे module.west.school_locker.row[3]
1🧩 एका विंगचा एक आराखडाmodules/wingvariable "wing" {}variable "lockers" { default = 2 }school_room "this" (सभागृह) name = "${var.wing}-hall"school_gate "this" room_id = school_room.this.idschool_locker "row" count = var.lockersoutput "gate_id"output "hall_id"inputs: wing, lockersoutputs: gate_id, hall_idएकदाच लिहिलेला, विंगसाठीच्याप्रमाणित आराखड्यासारखा2🏗️ दोनदा बोलावला — प्रत्येक call चे स्वतःचे inputs, addresses आणि outputsmodule "east" { wing = "east" }module.east · 4 resourceseast-hallroom-01east-gategate-01row[0]locker-01row[1]locker-02module "west" { wing = "west", lockers = 3 }module.west · 5 resourceswest-hallroom-02west-gategate-02row[0]locker-03row[1]locker-04row[2]locker-05Plan: 9 to add, 0 to change, 0 to destroy.Apply complete! Resources: 9 added, 0 changed, 0 destroyed.output east_gate = "gate-01" ← module.east.gate_idoutput west_hall = "room-02" ← module.west.hall_id3➕ west ला 4 lockers हवे — फक्त west बदलतेmodule "west" { …, lockers = 4 }+module.west.school_locker.row[3](create)Plan: 1 to add, 0 to change, 0 to destroy.[0][1][2][3]east ला हातही लागत नाही
⏪ आधी

प्रत्येक नवीन wing मागच्या wing चे blocks हाताने copy करत असे, आणि एका copy मधली दुरुस्ती इतरांपर्यंत पोहोचत नसे.

💡 काय

Module म्हणजे inputs (wing, lockers) आणि outputs (gate_id, hall_id) असलेला एक wing आराखडा, हवा तितक्या वेळा वापरता येतो.

⚙️ कसे

East ला 2 lockers आणि west ला 3: Plan: 9 to add. Outputs east_gate = gate-01 आणि west_hall = room-02.

🎯 का

West ने 4 lockers मागितले तर फक्त module.west.school_locker.row[3] वाढतो: 1 to add, east ला धक्का लागत नाही.

🚀 पुढे

पुढचा धडा नोंदवही एका सामायिक जागी नेतो, कारण दोन लोकांकडे दोन प्रती असल्या की गोंधळ होतो.

🧪 इथे करून पाहा — wing module वेगवेगळ्या inputs सह बोलवा
23

पूर्ण धडा 07 वाचा →

8 🔒 Remote state आणि locking

एकाच सामायिक जागी एक नोंदवही, एका वेळी एकच लिहिणारा.

🧒 सोप्या शब्दांत

सोमवारी कतरिना आणि दीपिका दोघी नोंदवहीची प्रत घेतात. त्यात लिहिले आहे: एक lab. कतरिना gym बांधते. दीपिका library बांधते. कतरिना आपली प्रत परत लिहिते, मग दीपिका आपली प्रत त्यावर लिहिते. आता नोंदवही gym विसरते. Gym उभे आहे पण त्याची काळजी कोणी घेत नाही. म्हणून office कुलूप आणते: कतरिनाकडे कुलूप असताना दीपिकाने थांबायचे.

📖 नवे शब्दremote state — एकाच सामायिक जागी ठेवलेली एक नोंदवही, laptop वर नाहीbackend — नोंदवही साठवणारी सामायिक जागा, जसे bucketstate lock — नोंदवही बदलताना एका वेळी फक्त एकीकडे राहणारी किल्लीorphan — बांधलेली आणि पैसे भरलेली, पण नोंदवहीला माहीत नसलेली गोष्ट
1❌ lock नाही — कतरिना व्यायामशाळा जोडते, दीपिका ग्रंथालय जोडते, एकाच वेळीनोंदवही · serial 1labKatrinaDipikaदोघींनी वाचलेserial 1+school_room.gym+school_room.library1 to add1 to addकतरिनाचे लिखाणlabgymदीपिकाचे लिखाण (शेवटचे)lablibraryपुसून पुन्हा लिहिलेदोघींनी serial 2 लिहिले —शेवटचे लिखाण जिंकतेपरिसर: 3 खोल्याlabroom-01libraryroom-03gymroom-02अनाथनोंदवहीला 2 खोल्या माहीत · व्यायामशाळा बांधली, पैसे भरले, पण कोणीच सांभाळत नाही2🔒 lock सह — एका वेळी एकच लिहिणारीremote backendcampus.tfstateएक नोंदवही,एक सामायिक जागा1Katrinalock-0001 घेते · व्यायामशाळेचा plan + apply → serial 22DipikaError acquiring the state lock · ID lock-0001 · Who katrina@works-office3Dipikalock-0002 मिळते · नवी नोंदवही वाचते → 1 to add, 0 to change, 1 to destroy← तिच्या branch मध्येव्यायामशाळा नाही4Dipikaआधी कतरिनाचा बदल pull करते → 1 to add, 0 to change, 0 to destroy5DipikaApply complete! 1 added → serial 3 · परिसरातील खोल्या 3 = नोंदवही 3lock शर्यतीचे रांगेत रूपांतर करते; आधी pull केल्याने अचानक होणारा destroy साध्या add मध्ये बदलतो
⏪ आधी

नोंदवही एका laptop वर किंवा git मध्ये होती, आणि दोन लोक एकाच वेळी plan करून ती लिहू शकत.

💡 काय

Remote state एकच नोंदवही सामायिक backend मध्ये ठेवते, आणि कुलूप असल्याने एका वेळी एकच लिहिणारी काम करते.

⚙️ कसे

कुलूप नाही: कतरिना आणि दीपिका दोघी serial 1 वाचतात आणि serial 2 लिहितात; दीपिका शेवटी लिहिते, म्हणून gym orphan होते.

🎯 का

कुलूप असताना दीपिकाला 'Error acquiring the state lock' येतो, ती कतरिनाचा बदल घेते, आणि serial 3: 3 खोल्या = नोंदवहीत 3.

🚀 पुढे

पुढचा धडा कोणीही न लिहिलेले बदल शोधतो: console click, हाताने बांधलेले gate आणि नाव बदललेली खोली.

🧪 इथे करून पाहा — कतरिना व्यायामशाळा जोडते, दीपिका ग्रंथालय, एकाच वेळी

पूर्ण धडा 08 वाचा →

9 🌪️ Drift आणि import

कोणीतरी console मध्ये click केले: refresh, drift, ignore_changes, import आणि moved blocks.

🧒 सोप्या शब्दांत

दीपिका console मध्ये click करून lab ला 45 seats देते. आराखड्यात अजून 30 आहेत. Contractor हे ओळखतो आणि ते परत 30 करायला सांगतो. मग ऐश्वर्याला कोणीतरी हाताने बांधलेले back gate सापडते. ती import ओळ जोडते, म्हणजे दुसरे gate न बांधता आराखडा तेच gate स्वीकारतो. खोलीचे नाव बदलले तर moved ओळ सांगते की ती तीच खोली आहे.

📖 नवे शब्दdrift — खरा campus बदलला, पण आराखडा आणि नोंदवही नाहीrefresh — काय बदलले ते पाहण्यासाठी खरा campus वाचणेimport — हाताने बांधलेली गोष्ट नोंदवहीत स्वीकारणेmoved — जुने नाव आणि नवे नाव एकच गोष्ट आहे असे सांगणारी नोंद
1🌪️ दीपिका console मध्ये click करते: room-01 जागा 30 → 45आराखडाseats = 30seats = 30नोंदवहीstateजागा 30seats = 30परिसर45 जागाseats = 45आराखडा किंवा नोंदवही कोणीच बदलली नाही— परिसर drift झालाplan -refresh-only → school_room.lab has changed outside of Terraform: seats 30 → 45~school_room.labseats: 45 → 30Plan: 0 to add, 1 to change, 0 to destroy.ignore_changes = [seats] → No changes.apply → 0 added, 1 changed · जागा पुन्हा 302🚪 हाताने बांधलेले मागचे फाटक: gate-02back-gategate-02नोंदवहीत नाहीimport शिवाय+school_gate.back(create)→ दुसरे फाटक · Plan: 1 to addimport block सहimport { to = school_gate.back, id = "gate-02" }←school_gate.backwill be imported (id gate-02)Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.3🏷️ आराखड्यात lab → science असे नाव बदलाmoved block शिवाय-/+lab-/+main-/+backPlan: 3 to add, 0 to change, 3 to destroy.lab आणि दोन्ही फाटके (त्यांचा room_id बदलतो) पुन्हा बांधली जातीलmoved { from = school_room.lab, to = school_room.science } सहआधीची नोंदवहीschool_room.labनंतरची नोंदवहीschool_room.scienceroom-01 तसेच राहते · has moved · Plan: 0 to add, 0 to change, 0 to destroy.import हाताने बांधलेली वस्तू आराखड्याखाली आणतो · moved पुन्हा न बांधता address चे नाव बदलतो
⏪ आधी

कोणीतरी console मध्ये खोली बदलली आणि पुढच्या बांधकामाने ती गुपचूप परत बदलेपर्यंत कोणाला कळले नाही.

💡 काय

Drift म्हणजे campus नोंदवहीपेक्षा वेगळा असणे; import हाताने बांधलेली वस्तू स्वीकारतो, moved address चे नाव बदलतो.

⚙️ कसे

दीपिका room-01 चे seats 30 → 45 करते; plan ~ seats 45 → 30 दाखवतो, आणि ignore_changes = [seats] ने No changes.

🎯 का

Import शिवाय gate-02 च्या शेजारी दुसरे gate बनते; moved शिवाय नाव बदलल्याने 0 ऐवजी 3 to add आणि 3 to destroy.

🚀 पुढे

पुढचा धडा तेच आराखडे dev आणि prod साठी चालवतो, आणि चुकीची site किती सहज बदलते ते दाखवतो.

🧪 इथे करून पाहा — कोणीतरी console मध्ये click केले — refresh, ignore, import, move
45

पूर्ण धडा 09 वाचा →

10 🏘️ Environments

त्याच आराखड्यांवरून dev आणि prod: workspaces विरुद्ध directories विरुद्ध वेगळे accounts.

🧒 सोप्या शब्दांत

शाळा एक लहान सरावाचा campus आणि खरा campus चालवते. दोघांसाठी एकच आराखडा. प्रत्येकाची स्वतःची नोंदवही आणि स्वतःची settings file. Dev मध्ये 10 seats आणि 1 locker. Prod मध्ये 40 seats आणि 3 lockers. एके दिवशी कतरिनाने prod उघडलेले असते पण ती dev file वापरते. Plan prod लहान करू पाहतो. सुदैवाने ती plan वाचते आणि नाही म्हणते.

📖 नवे शब्दenvironment — campus ची एक प्रत, जसे सरावासाठी dev किंवा खऱ्यासाठी prodworkspace — त्याच आराखड्यासाठी वेगळी नोंदवही, प्रत्येक environment ला एक.tfvars file — एका environment ची मूल्ये असलेली settings fileseparate accounts — dev आणि prod वेगवेगळ्या accounts मध्ये, सर्वात मजबूत भिंत
1🏘️ एक आराखडा, दोन workspaces, प्रत्येकी एक .tfvars filecampus.tfname = "${terraform. workspace}-lab"seats = var.seatscount = var.lockersdev.tfvars: seats 10, lockers 1prod.tfvars: seats 40, lockers 3workspace devdev-lab · 10 जागाroom-01locker-01Apply complete! 2 addedworkspace prodprod-lab · 40 जागाroom-02locker-02locker-03locker-04Apply complete! 4 addedbackendenv:/dev/campus.tfstateenv:/prod/campus.tfstateप्रत्येक workspace ची एक नोंदवहीपरिसरात 6 वस्तू2😬 कतरिना `workspace select dev` विसरते — prod निवडलेले आहे, dev.tfvars वापरली जातेKatrinaworkspace: prod-var-file=dev.tfvars~school_room.labseats: 40 → 10-school_locker.row[1](destroy)-school_locker.row[2](destroy)Plan: 0 to add, 1 to change, 2 to destroy.prod-lab · 40 → 10prod आकुंचन पावूनdev एवढे होते3🧱 dev आणि prod वेगळे ठेवण्याचे तीन मार्ग — पडद्यापासून भिंतीपर्यंतworkspacesतोच code, तोच backend, प्रत्येक workspace ला एक stateझटपट — पण एक चुकीचा select prod ला फटका देतोdirectoriesenvs/dev आणि envs/prod तेच modules बोलावतातप्रत्येकाची स्वतःची backend key · थोडी नक्कलaccountsवेगवेगळी cloud accounts, state आणि CI rolesdev आणि prod यांच्यातील सर्वात मजबूत भिंत
⏪ आधी

एकच environment होते, म्हणून प्रत्येक बदल थेट production मध्ये तपासला जाई, किंवा dev ही हाताने केलेली प्रत होती.

💡 काय

एकच आराखडा, प्रत्येक environment साठी एक workspace, आणि प्रत्येकी एक .tfvars file: dev.tfvars आणि prod.tfvars.

⚙️ कसे

Dev (10 seats, 1 locker) मध्ये 2 added, prod (40 seats, 3 lockers) मध्ये 4: नोंदवह्या env:/dev आणि env:/prod, 6 वस्तू.

🎯 का

prod निवडलेले असताना कतरिना dev.tfvars ने plan करते: seats 40 → 10 आणि 2 lockers destroy. Prod dev एवढे लहान होते.

🚀 पुढे

पुढच्या धड्यात बांधकामाआधी तपासनीस येतात: validate, tests, policy आणि cost सगळे plan वाचतात.

🧪 इथे करून पाहा — निवडलेले workspace आणि .tfvars फाइल निवडा

पूर्ण धडा 10 वाचा →

11 🧪 Testing आणि policy

Validate, tests, policy आणि cost — काहीही बांधण्याआधी plan वाचणारे निरीक्षक.

🧒 सोप्या शब्दांत

काहीही बांधण्याआधी चार तपासनीस आराखडा वाचतात. पहिली लिखाण तपासते आणि तिला 4 चुका सापडतात. दुसरी छोट्या tests चालवते: 2 pass, 1 fail. तिसरी शाळेचे नियम तपासते आणि रात्रभर उघडे राहणारे gate थांबवते. चौथी खर्च मोजते: महिन्याला 2830 रुपये. हे सगळे कागदावरच होते.

📖 नवे शब्दvalidate — campus शिवाय, आराखडा बरोबर लिहिला आहे का ते तपासणेtest — plan ला हवा तोच अर्थ आहे का याची छोटी तपासणीpolicy — एखाद्या बदलाला DENY म्हणू शकणारा शाळेचा नियमcost estimate — बांधण्याआधी, plan ला दर महिन्याला किती खर्च येईल
1🧪 काहीही बांधण्याआधी चार तपासनीस आराखडा वाचतातआराखडाgymnight-gateमोठा locker …📐 validateआराखड्याचा आकार तपासतो🧪 testsत्याचा अर्थ काय आहे ते तपासतो🛂 policyकशाला परवानगी आहे ते तपासतो💰 खर्चत्याला किती खर्च येतो ते तपासतो2📐 validate — campus ची गरज नाहीgym { floor = 1 seats = "thirty" colour = "blue"}बिघडलेला configschool_room.gym: "seats": a number is required.school_room.gym: "colour" is not expected here.school_room.gym: "name" is required, butno definition was found.school_gate.g: undeclared resource"school_room.pool".4 errors → काहीही plan होत नाही3🧪 terraform test (command = plan)run "the lab has 30 seats"... passrun "the lab gets 2 lockers"... passrun "gates close at night"... failError: Test assertion failed — a gate is open 00-24Failure! 2 passed, 1 failed.4🛂 plan वर policy (dev) — Plan: 5 to addDENYschool_room.gymप्रत्येक room ला owner tag हवा (tags मध्ये 'owner' नाही)DENYschool_gate.nightफाटके रात्री बंद व्हायलाच हवीत (open_hours = '00-24')xlDENYschool_locker.bigprod बाहेर xl lockers नकोत (dev मध्ये size = 'xl')5💰 खर्च: ₹0/महिना → ₹2830/महिना (+2830)lab₹1200gym₹1200night-gate₹300मोठा (xl)₹90a (m)₹40₹₹काल्पनिक किमती — Infracost comment चा आकार
⏪ आधी

चुका बांधकामानंतर सापडत: उघडे gate, owner नसलेली खोली, महिन्याच्या शेवटी मोठे बिल.

💡 काय

चार तपासनीस आधी आराखडा वाचतात: validate आकार, tests अर्थ, policy काय परवानगी आहे, आणि cost किंमत तपासते.

⚙️ कसे

Validate ला 4 errors सापडतात; policy 3 बदल नाकारते; cost ₹0 → ₹2830/month; tests: 2 passed, 1 failed.

🎯 का

00-24 उघडे राहणारे night gate कागदावरच थांबते, कोणतेही gate बांधण्याआधी किंवा एकही रुपया खर्च होण्याआधी.

🚀 पुढे

पुढचा धडा सगळे एका conveyor belt वर ठेवतो: pull request वर plan, merge वर apply, keys ऐवजी OIDC.

🧪 इथे करून पाहा — आराखडा बदला — validate, policy, cost आणि tests पुन्हा चालतात
30

पूर्ण धडा 11 वाचा →

12 🚀 CI/CD मध्ये IaC आणि संपूर्ण चित्र

Pull request वर plan, merge वर apply, keys ऐवजी OIDC — आणि संपूर्ण चित्र.

🧒 सोप्या शब्दांत

आता एक conveyor belt काम करतो. दीपिका बदलाची विनंती उघडते, आणि belt ती तपासून plan दाखवतो. ऐश्वर्या तो तपासते. Merge झाला की belt बांधकाम करतो. Belt कडे साठवलेली किल्ली नसते: तो एक तास टिकणारा pass दाखवतो. दोन बदल शर्यत लावतात तेव्हा belt जुना plan नाकारतो आणि नवी तपासणी मागतो.

📖 नवे शब्दpull request — आराखडा बदलण्याची विनंती जी आधी इतर जण तपासतातCI/CD — तुमच्यासाठी बदल तपासणारा, plan करणारा आणि apply करणारा conveyor beltOIDC token — साठवलेल्या किल्लीऐवजी job दाखवतो तो थोडा वेळ टिकणारा passstale plan — दुसऱ्या कोणी नोंदवही बदलण्याआधी बनवलेला plan
1🪪 CI job अल्पकाळ टिकणारा OIDC token दाखवतो — साठवलेल्या cloud keys नाहीत🎫 pull_requestsub=repo:school/campus-infra:pull_request🎫 main वर pushsub=repo:school/campus-infra:ref:refs/heads/maincampus-planread-only (plan)campus-applyread-write (apply) · फक्त mainमंजूर · 3600 sAccessDeniedमंजूर · 3600 sमंजूर · 3600 splan role repo:school/campus-infra:* वर विश्वास ठेवतो · apply role फक्त …:ref:refs/heads/main वर विश्वास ठेवतो2🏁 दोन pull requests, एक नोंदवही — जुना (stale) plan नाकारला जातोserialstate 1state 2state 3PR #43 · मुख्य फाटकplan @1 → 1 to addखर्च +300merge → apply → serial 2PR #42 · एक ग्रंथालयplan @1 → 1 to addखर्च +1200merge: जतन केलेला plan जुना (stale) झाला आहेre-plan: 1 add, 1 destroyPR #42 rebasedplan @2 → 1 to addmerge → apply → serial 3थांबाकाहीही apply झाले नाहीre-plan हा review केलेला plan नाही (तो नवे फाटक destroy करेल) → थांबा, rebase करा, पुन्हा review करा3🗺️ संपूर्ण चित्र📜 git मध्ये आराखडा🧪 validate · test · policy · cost📋 PR वर plan👀 review🚀 merge झाल्यावर apply (OIDC)🔒 एक कुलूपबंद नोंदवहीrefresh ला drift सापडतो → import आणि moved नोंदवही प्रामाणिक ठेवतात → प्रत्येक जागेसाठी तोच आराखडा
⏪ आधी

कोणी laptop वरून apply चालवत असे, आणि सगळ्या jobs मध्ये वाटलेली long-lived cloud key CI secret मध्ये ठेवलेली असे.

💡 काय

CI प्रत्येक pull request वर plan आणि merge वर apply चालवते, साठवलेल्या keys ऐवजी short-lived OIDC tokens वापरून.

⚙️ कसे

pull_request token ला campus-plan (3600 s) मिळते पण campus-apply ला AccessDenied; फक्त main apply करू शकते.

🎯 का

#43 apply झाल्यावर #42 चा saved plan stale झाला: re-plan ला 1 to destroy हवे होते, म्हणून थांबला; rebase नंतर serial 3.

🚀 पुढे

पुढे: AWS school हा campus आहे जो हे आराखडे सहसा बांधतात, आणि CI/CD school pipeline चालवते.

🧪 इथे करून पाहा — कोण plan किंवा apply करू शकते — आणि कोणता merge जिंकतो

पूर्ण धडा 12 वाचा →

धडा 01 सुरू करा → 🗓️ अभ्यास योजना (4 आठवडे) 📐 सर्व 12 धड्यांच्या आकृत्या 🧪 प्रश्नमंजुषा (16 प्रश्न) ⏮️ आधी काय होते & फायदे-तोटे