ЁЯПШя╕П рдзрдбрд╛ 10 тАФ Environments: рддреНрдпрд╛рдЪ рдЖрд░рд╛рдЦрдбреНрдпрд╛рд╡рд░реВрди dev рдЖрдгрд┐ prod
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 10 ┬╖ рдорд╛рдЧреАрд▓: lesson-09-drift-import ┬╖ рдкреБрдвреАрд▓: lesson-11-testing-policy
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ09, рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд рдЕрдиреЗрдХ рдЬрд╛рдЧрд╛. рддреЛрдЪ рдЖрд░рд╛рдЦрдбрд╛ рдПрдХ рд▓рд╣рд╛рди dev campus рдЖрдгрд┐ рдПрдХ
рдореЛрдард╛ prod campus рдмрд╛рдВрдзрд╛рдпрд▓рд╛ рд╣рд╡рд╛, рдЖрдгрд┐ рдПрдХрд╛рддрд▓рд╛ рдмрджрд▓ рджреБрд╕рд▒реНрдпрд╛рд▓рд╛ рдХрдзреАрдЪ рд╣рд╛рдд рд▓рд╛рд╡рддрд╛ рдХрд╛рдорд╛ рдирдпреЗ. рдпрд╛рдЪреЗ рддреАрди рдиреЗрд╣рдореАрдЪреЗ рдорд╛рд░реНрдЧ:
workspaces (рдПрдХ config, рдПрдХ backend, рдкреНрд░рддреНрдпреЗрдХ workspace рдЪреА рд╡реЗрдЧрд│реА state), рд╡реЗрдЧрд│реНрдпрд╛
directories (рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА рдПрдХ folder, рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА backend key, modules рд╕рд╛рдорд╛рдпрд┐рдХ)
рдЖрдгрд┐ рд╡реЗрдЧрд│реЗ accounts (рд╢рд┐рд╡рд╛рдп рд╡реЗрдЧрд│реА state рдЖрдгрд┐ рд╡реЗрдЧрд│реЗ CI roles).
environments() рд╣реЗ iac/demo.py рдордзреНрдпреЗ рдЖрд╣реЗ; Backend.path() рд╣реЗ
iac/engine.py рдордзреНрдпреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдХрдбреЗ рдПрдХ рд╕рд░рд╛рд╡рд╛рдЪрд╛ campus (dev) рдЖрд╣реЗ рдЬрд┐рдереЗ рдирд╡реНрдпрд╛ рдХрд▓реНрдкрдирд╛ рдХрд░реВрди рдкрд╛рд╣рд┐рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд, рдЖрдгрд┐ рдПрдХ рдЦрд░рд╛
campus (prod) рдЬрд┐рдереЗ рдореБрд▓реЗ рдЕрд╕рддрд╛рдд. ЁЯПлЁЯПл рдЖрд░рд╛рдЦрдбрд╛ рддреЛрдЪ, рдЖрдХрд╛рд░ рд╡реЗрдЧрд│реЗ: рд╕рд░рд╛рд╡рд╛рдЪреНрдпрд╛ lab рдордзреНрдпреЗ
10 seats рдЖрдгрд┐ 1 locker; рдЦрд▒реНрдпрд╛ lab рдордзреНрдпреЗ 40 seats рдЖрдгрд┐ 3 lockers. рд╣реЗ рдЖрдХрд╛рд░ рджреЛрди
рд▓рд╣рд╛рди рдХрд╛рд░реНрдбрд╛рдВрд╡рд░ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЕрд╕рддрд╛рдд: dev.tfvars рдЖрдгрд┐ prod.tfvars. ЁЯГП
рдорд╛рд░реНрдЧ 1 тАФ workspaces. рдПрдХрдЪ рдиреЛрдВрджрд╡рд╣реА, рдкрдг рддрд┐рд▓рд╛ рджреЛрди tabs: "dev" рдЖрдгрд┐ "prod". рдХрд╛рдо рдХрд░рдгреНрдпрд╛рдЖрдзреА рддреБрдореНрд╣реА рдпреЛрдЧреНрдп tab рдЙрдШрдбрддрд╛. рдХрддрд░рд┐рдирд╛ prod tab рдЙрдШрдбрддреЗ рдкрдг рдЪреБрдХреВрди dev рдЪреЗ рдХрд╛рд░реНрдб рдЙрдЪрд▓рддреЗ. рдХрдВрддреНрд░рд╛рдЯрджрд╛рд░ plan рдореЛрдареНрдпрд╛рдиреЗ рд╡рд╛рдЪрддреЛ: "рдЦрд░реА lab: 40 seats тЖТ 10. 2 lockers рдХрд╛рдвреВрди рдЯрд╛рдХрд╛." рдирд╢реАрдм, рдХрддрд░рд┐рдирд╛ рд╣реЛ рдореНрд╣рдгрдгреНрдпрд╛рдЖрдзреА plans рд╡рд╛рдЪрддреЗ. ЁЯШЕ
рдорд╛рд░реНрдЧ 2 тАФ рд╡реЗрдЧрд│реЗ folders. dev рд╕рд╛рдареА рдПрдХ folder, prod рд╕рд╛рдареА рдПрдХ folder, рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА рдиреЛрдВрджрд╡рд╣реА. рддреБрдореНрд╣реА "рдЪреБрдХреАрдЪреНрдпрд╛ tab рдордзреНрдпреЗ" рдЕрд╕реВрдЪ рд╢рдХрдд рдирд╛рд╣реА тАФ рддреБрдореНрд╣реА рд╡реЗрдЧрд│реНрдпрд╛рдЪ рдЦреЛрд▓реАрдд рдЙрднреЗ рдЕрд╕рддрд╛.
рдорд╛рд░реНрдЧ 3 тАФ рд╡реЗрдЧрд│реЗ campuses. dev рдЖрдгрд┐ prod рдпрд╛ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдЬрд╛рдЧрд╛ рдЖрд╣реЗрдд, рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛рдВрд╕рд╣. рд╕рд░рд╛рд╡ рдХрд░рдгрд╛рд▒реНрдпрд╛ рдмрд╛рдВрдзрдХрд╛рдо рдХрд░рдгрд╛рд▒реНрдпрд╛рдВрдЪреНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛ рдЦрд▒реНрдпрд╛ campus рдЪреЗ рдлрд╛рдЯрдХрд╣реА рдЙрдШрдбрдд рдирд╛рд╣реАрдд. ЁЯФС
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
plans["ЁЯУЬ one set of plans + modules"]
plans -->|"workspace dev + dev.tfvars"| d["ЁЯУТ env:/dev/campus.tfstate<br/>dev-lab ┬╖ 10 seats ┬╖ 1 locker"]
plans -->|"workspace prod + prod.tfvars"| p["ЁЯУТ env:/prod/campus.tfstate<br/>prod-lab ┬╖ 40 seats ┬╖ 3 lockers"]
oops["тЪая╕П prod selected + dev.tfvars"] --> bad["~ seats 40 тЖТ 10<br/>- 2 lockers"]
ЁЯЧ║я╕П рд░реЗрдЦрд╛рдЯрд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/terraform/lesson-diagrams.html#l10
тЭУ рдХрд╛рдп
- Environment тАФ рдПрдХрд╛ рдЙрджреНрджреЗрд╢рд╛рд╕рд╛рдареА system рдЪреА рдкреВрд░реНрдг рдкреНрд░рдд: dev, test, staging, prod. рд░рдЪрдирд╛ рддреАрдЪ, рдЖрдХрд╛рд░, data рдЖрдгрд┐ access рд╡реЗрдЧрд│реЗ.
- CLI workspaces тАФ
terraform workspace new dev,select dev,show. рдПрдХ config, рдПрдХ backend, рдкреНрд░рддреНрдпреЗрдХ workspace рдЪреА рд╡реЗрдЧрд│реА state.terraform.workspaceрдордзреНрдпреЗ рдирд╛рд╡ рдЕрд╕рддреЗ. S3 backend рд╕реЛрдмрдд, default рдирд╕рд▓реЗрд▓реЗ workspacesenv:/<workspace>/<key>рдЦрд╛рд▓реА рд╕рд╛рдард╡рд▓реЗ рдЬрд╛рддрд╛рдд (рд╣рд╛workspace_key_prefix, default рдореНрд╣рдгреВрдиenv:). - рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА
.tfvarsтАФterraform plan -var-file=prod.tfvars. Config рддреЗрдЪ рд░рд╛рд╣рддреЗ; рдореВрд▓реНрдпреЗ рдмрджрд▓рддрд╛рдд. - рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА directory тАФ
envs/dev/main.tfрдЖрдгрд┐envs/prod/main.tf, рдкреНрд░рддреНрдпреЗрдХ рдПрдХ рд▓рд╣рд╛рди root module рдЬреЗ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдореВрд▓реНрдпрд╛рдВрд╕рд╣ рд╕рд╛рдорд╛рдпрд┐рдХ modules рдмреЛрд▓рд╛рд╡рддреЗ рдЖрдгрд┐ рдЬреНрдпрд╛рдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ backend block рдЕрд╕рддреЛ. рдкреНрд░рддреНрдпреЗрдХ directory рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ initialise рдЖрдгрд┐ apply рдХреЗрд▓реА рдЬрд╛рддреЗ. - рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА account тАФ dev рдЖрдгрд┐ prod рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ cloud accounts рдордзреНрдпреЗ (рдХрд┐рдВрд╡рд╛ subscriptions, projects), рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ credentials рд╕рд╣. рд╕рд░реНрд╡рд╛рдд рдордЬрдмреВрдд рд╡реЗрдЧрд│реЗрдкрдгрд╛: dev role prod рд▓рд╛ рдЕрдЬрд┐рдмрд╛рдд рд╣рд╛рдд рд▓рд╛рд╡реВ рд╢рдХрдд рдирд╛рд╣реА.
- HCP Terraform workspaces тАФ рддреНрдпрд╛рдЪ рдирд╛рд╡рд╛рдЪреА рдкрдг рд╡реЗрдЧрд│реА рдЧреЛрд╖реНрдЯ: HCP Terraform рдордзреНрдпреЗ workspace рдореНрд╣рдгрдЬреЗ рд╕реНрд╡рддрдГрдЪреА state, variables, permissions рдЖрдгрд┐ run history рдЕрд╕рд▓реЗрд▓реЗ рдкреВрд░реНрдг рдПрдХрдХ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "staging рдордзреНрдпреЗ test рдХреЗрд▓реЗ" рдпрд╛рд▓рд╛ рдЕрд░реНрде рддреЗрд╡реНрд╣рд╛рдЪ рдЕрд╕рддреЛ рдЬреЗрд╡реНрд╣рд╛ staging рддреНрдпрд╛рдЪ рдЖрд░рд╛рдЦрдбреНрдпрд╛рд╡рд░реВрди рдмрд╛рдВрдзрд▓реЗрд▓реЗ рдЕрд╕рддреЗ. рдЖрдгрд┐ рдХрд╛рд░рдг IaC рдордзреАрд▓ рд╕рд░реНрд╡рд╛рдд рдорд╣рд╛рдЧрдбреНрдпрд╛ рдЪреБрдХрд╛ рдореНрд╣рдгрдЬреЗ рдЪреБрдХреАрдЪреНрдпрд╛ environment рд╡рд░ apply рдХреЗрд▓реЗрд▓реЗ рдЖрд░рд╛рдЦрдбреЗ. HashiCorp рдЪреЗ рд╕реНрд╡рддрдГрдЪреЗ documentation рд╕рд╛рдВрдЧрддреЗ рдХреА environments рдирд╛ рд╡реЗрдЧрд│реЗ credentials рдХрд┐рдВрд╡рд╛ access controls рд╣рд╡реЗ рдЕрд╕рддреАрд▓, рддреЗрд╡реНрд╣рд╛ CLI workspaces рдпреЛрдЧреНрдп рдирд╛рд╣реАрдд. Environments рддреНрдпрд╛рдВрдирд╛ рдХреЛрдг рдмрджрд▓реВ рд╢рдХрддреЗ рдпрд╛рдд рдЬрд┐рддрдХреЗ рд╡реЗрдЧрд│реЗ, рддрд┐рддрдХреА рддреНрдпрд╛рдВрдирд╛ рд╡реЗрдЧрд│реНрдпрд╛ directories, backends рдЖрдгрд┐ accounts рдЪреА рдЬрд╛рд╕реНрдд рдЧрд░рдЬ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
iac/engine.py рдордзреАрд▓ Backend.path(workspace) default рд╕рд╛рдареА campus.tfstate
рдЖрдгрд┐ рдЗрддрд░рд╛рдВрд╕рд╛рдареА env:/<workspace>/campus.tfstate рдкрд░рдд рджреЗрддреЗ. plan(..., workspace=ws) рдореБрд│реЗ ${terraform.workspace} рдЪреЗ рдореВрд▓реНрдп workspace рдЪреЗ рдирд╛рд╡ рд╣реЛрддреЗ.
iac/demo.py рдордзреАрд▓ ENV lab рдЪреЗ рдирд╛рд╡ ${terraform.workspace}-lab рдареЗрд╡рддреЗ рдЖрдгрд┐
seats рд╡ lockers TFVARS рдордзреВрди рдШреЗрддреЗ. Demo dev рдЖрдгрд┐ prod apply рдХрд░рддреЛ, рдордЧ dev рдЪреНрдпрд╛
рдореВрд▓реНрдпрд╛рдВрдиреА prod рдЪрд╛ plan рдХрд░рддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 iac/demo.py environments
python3 - <<'EOF'
import sys; sys.path.insert(0, "iac")
from cloud import FakeCloud
from engine import plan, apply, Backend
from demo import ENV
cloud, be = FakeCloud(), Backend()
vars = {"dev": {"seats": 10, "lockers": 1}, "staging": {"seats": 20, "lockers": 2}, "prod": {"seats": 40, "lockers": 3}}
for ws, v in vars.items():
st, _, msg = apply(plan(ENV, be.read(be.path(ws)), cloud, vars=v, workspace=ws), cloud, backend=be, key=be.path(ws))
names = [r["attrs"]["name"] for r in st["resources"].values() if r["type"] == "school_room"]
print(f"{ws:<8} {be.path(ws):<27} {len(st['resources'])} resources ┬╖ room {names}")
print("campus objects:", len(cloud.inventory()), "┬╖ default workspace empty:", be.read(be.path())["resources"] == {})
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
environments рд╣реЗ рдЫрд╛рдкрддреЗ:
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
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
dev env:/dev/campus.tfstate 2 resources ┬╖ room ['dev-lab']
staging env:/staging/campus.tfstate 3 resources ┬╖ room ['staging-lab']
prod env:/prod/campus.tfstate 4 resources ┬╖ room ['prod-lab']
campus objects: 9 ┬╖ default workspace empty: True
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдПрдХрд╛рдЪ рдЖрд░рд╛рдЦрдбреНрдпрд╛рдиреЗ рддреАрди рд╡реЗрдЧрд│реЗ environments рдмрд╛рдВрдзрд▓реЗ, рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА рдиреЛрдВрджрд╡рд╣реА key рдЖрдгрд┐
рд╕реНрд╡рддрдГрдЪрд╛ рдЖрдХрд╛рд░ тАФ рдЖрдгрд┐ default workspace рд░рд┐рдХрд╛рдореЗ рд░рд╛рд╣рд┐рд▓реЗ. рдкрдг рддрд┐рдиреНрд╣реА рдПрдХрд╛рдЪ
campus рдордзреНрдпреЗ рдЖрдгрд┐ рдПрдХрд╛рдЪ backend рдордзреНрдпреЗ рд░рд╛рд╣рддрд╛рдд, рдЖрдгрд┐ рдирд┐рд╡рдбрд▓реЗрд▓реНрдпрд╛ workspace рд╢рд┐рд╡рд╛рдп рддреНрдпрд╛рдВрдирд╛ рдХрд╛рд╣реАрдЪ рд╡реЗрдЧрд│реЗ рдХрд░рдд рдирд╛рд╣реА: рдЪреБрдХреАрдЪреНрдпрд╛
workspace рд╕реЛрдмрдд рдЪреБрдХреАрдЪреНрдпрд╛ .tfvars рдиреЗ prod рд▓рд╣рд╛рди рдХрд░рдгреНрдпрд╛рдЪрд╛ plan рдХреЗрд▓рд╛ (1 to change, 2 to destroy).
рддреНрдпрд╛ рдЖрдгрд┐ outage рдЪреНрдпрд╛ рдордзреНрдпреЗ рдлрдХреНрдд plan review рдЙрднрд╛ рд╣реЛрддрд╛.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рддреНрдпрд╛рдЪ credentials рд╕рд╣ CLI workspaces рдореНрд╣рдгреВрди dev рдЖрдгрд┐ prod тАФ prod рдкрд╛рд╕реВрди рдлрдХреНрдд рдПрдХрд╛ рдЪреБрдХреАрдЪреНрдпрд╛
selectрдЪреЗ рдЕрдВрддрд░ - copy-paste рдХреЗрд▓реЗрд▓реЗ environment folders рдЬреЗ рд╣рд│реВрд╣рд│реВ рд╡реЗрдЧрд│реЗ рд╣реЛрдд рдЬрд╛рддрд╛рдд тАФ modules рд╕рд╛рдорд╛рдпрд┐рдХ рдХрд░рд╛, folders рдкрд╛рддрд│ рдареЗрд╡рд╛
- рд╕рдЧрд│реАрдХрдбреЗ рд╢рд┐рдВрдкрдбрд▓реЗрд▓реЗ
count = terraform.workspace == "prod" ? 3 : 1тАФ рдЖрдХрд╛рд░.tfvarsрдордзреНрдпреЗ рдареЗрд╡рд╛ - рд╕рдЧрд│реНрдпрд╛ environments рд╕рд╛рдареА рдПрдХрдЪ state тАФ рдкреНрд░рддреНрдпреЗрдХ dev рдмрджрд▓ prod рд▓рд╛ lock рдХрд░рддреЛ рдЖрдгрд┐ рдзреЛрдХреНрдпрд╛рдд рдШрд╛рд▓рддреЛ
- plan output рдордзреНрдпреЗ environment рдЪреА рдХреЛрдгрддреАрд╣реА рджрд┐рд╕рдгрд╛рд░реА рдЦреВрдг рдирд╕рдгреЗ (рддреА names рдЖрдгрд┐ tags рдордзреНрдпреЗ рдареЗрд╡рд╛)
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ CLI workspaces, рдЬреЗрд╡реНрд╣рд╛ environments рдЪрд╛ access рд╕рд╛рдорд╛рдпрд┐рдХ рдЕрд╕рддреЛ:
terraform workspace new staging
terraform workspace select staging
terraform workspace show # always check before apply
terraform plan -var-file=staging.tfvars -out=tfplan
рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА рдПрдХ directory, рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рд╕реНрд╡рддрдГрдЪреА backend key, рд╕рд╛рдорд╛рдпрд┐рдХ modules рдмреЛрд▓рд╛рд╡рдгрд╛рд░реА:
infra/
тФЬтФАтФА modules/wing/ # the shared design
тФФтФАтФА envs/
тФЬтФАтФА dev/ main.tf backend.tf (key = "dev/campus.tfstate") dev.tfvars
тФФтФАтФА prod/ main.tf backend.tf (key = "prod/campus.tfstate") prod.tfvars
# envs/prod/main.tf
module "east" {
source = "../../modules/wing"
wing = "east"
lockers = 3
}
рд╡реЗрдЧрд│реНрдпрд╛ accounts рд╕рд╛рдареА, рдкреНрд░рддреНрдпреЗрдХ environment рдЪрд╛ provider рд╡реЗрдЧрд│рд╛ role assume рдХрд░рддреЛ, рдЖрдгрд┐ prod рдЪрд╛ CI job рд╣рд╛рдЪ prod role assume рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рдЕрд╕рд▓реЗрд▓рд╛ рдПрдХрдореЗрд╡ рдШрдЯрдХ рдЕрд╕рддреЛ (рдзрдбрд╛ 12). Terragrunt рд╕рд╛рд░рдЦреА tools рдореБрдЦреНрдпрддрдГ рдЕрдиреЗрдХ environment folders рд▓рд╣рд╛рди рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рдареА рдЕрд╕рддрд╛рдд.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ: prod рд╕рд╛рдареА рд▓рд┐рд╣реВрди рдареЗрд╡рд╛ рдХреА рддреЗ рдмрджрд▓рдгрд╛рд░реЗ credentials рдХреЛрдг рдЖрдгрд┐ рдХрд╛рдп assume рдХрд░реВ рд╢рдХрддреЗ. рдЙрддреНрддрд░рд╛рдд "dev рдЪрд╛рд▓рд╡реВ рд╢рдХрдгрд╛рд░реЗ рдХреЛрдгреАрд╣реА" рдЕрд╕реЗрд▓, рддрд░ environments рдЕрдЬреВрди рд╡реЗрдЧрд│реЗ рдЭрд╛рд▓реЗрд▓реЗ рдирд╛рд╣реАрдд.
тПня╕П рдкреБрдвреЗ
рдкреНрд░рддреНрдпреЗрдХ plan рдбреЛрд│реНрдпрд╛рдВрдиреА рд╡рд╛рдЪрдгреЗ рдореЛрдареНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рд╡рд░ рд╢рдХреНрдп рдирд╛рд╣реА. рдкреБрдвреЗ: рддреБрдордЪреНрдпрд╛рд╕рд╛рдареА рдЖрд░рд╛рдЦрдбрд╛ рд╡рд╛рдЪрдгрд╛рд░реЗ рддрдкрд╛рд╕рдиреАрд╕ тАФ validate, tests, policy рдЖрдгрд┐ cost.
git checkout lesson-11-testing-policy