Files
tf_provider/devops/04b_enrich_outputs_from_inventory.py
T

152 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Дополнительный генератор: обогащает *_outputs.md реальными ключами
из output_inventory (собранного со стендов).
Обновляет только секцию "## Реальные поля из облака" — не трогает остальное.
Запуск (из корня репо на VM):
python3 devops/04b_enrich_outputs_from_inventory.py [--dry-run]
"""
import json, yaml, glob, os, sys
BASE = "/home/naeel/terra/terraform"
YAML_DIR = f"{BASE}/devops/profiles/test/generated/resources_yaml"
INV_DIR = f"{BASE}/devops/profiles/test/generated/output_inventory"
DOCS_DIR = f"{BASE}/docs/30_registry/resources"
SECTION_MARKER = "## Реальные поля из облака"
def flatten(obj, prefix=""):
"""Рекурсивно собирает dot-notation ключи из вложенного dict/list."""
keys = []
if isinstance(obj, dict):
for k, v in obj.items():
full = f"{prefix}.{k}" if prefix else k
keys.append(full)
if isinstance(v, (dict, list)):
keys.extend(flatten(v, full))
elif isinstance(obj, list):
for i, v in enumerate(obj):
full = f"{prefix}.{i}" if prefix else str(i)
if isinstance(v, (dict, list)):
keys.extend(flatten(v, full))
# скалярные элементы списка не добавляем — нет смысла
return keys
def best_instance(instances):
"""Выбираем лучший инстанс: running с данными > suspended с данными."""
candidates = [i for i in instances if i.get("out") or i.get("params")]
if not candidates:
return None
running = [i for i in candidates if i.get("status") == "running"]
return running[-1] if running else candidates[-1]
def build_section(inst):
params = inst.get("params") or {}
out = inst.get("out") or {}
vault = inst.get("vault_keys") or []
source = inst.get("source", "test")
name = inst.get("name", "?")
status = inst.get("status", "?")
lines = [
f"{SECTION_MARKER} ({source} / {name} / {status})\n",
"\n",
"Поля ниже получены из реальных инстансов этого сервиса в облаке.\n",
"Используйте их как готовые ключи для `state_out_flat` и `vault_secrets`.\n",
]
if params:
lines.append("\n### `state_params` ключи\n\n")
for k in params.keys():
lines.append(f'- `state_params["{k}"]`\n')
flat_out = flatten(out)
if flat_out:
lines.append("\n### `state_out_flat` ключи\n\n")
for k in flat_out:
lines.append(f'- `state_out_flat["{k}"]`\n')
if vault:
lines.append("\n### `vault_secrets` ключи\n\n")
for k in vault:
lines.append(f'- `vault_secrets["{k}"]`\n')
return "".join(lines)
def main():
dry_run = "--dry-run" in sys.argv
# 1. service_id → name (из YAML)
svc_to_name = {}
for f in glob.glob(f"{YAML_DIR}/*.yaml"):
try:
d = yaml.safe_load(open(f))
sid = d.get("service_id")
name = d.get("name") or d.get("service_short_name")
if sid and name:
svc_to_name[sid] = name
except Exception:
pass
updated = 0
skipped = 0
for inv_file in sorted(glob.glob(f"{INV_DIR}/svc_*.json")):
if "index" in inv_file:
continue
inv = json.load(open(inv_file))
svc_id = inv.get("serviceId")
inst = best_instance(inv.get("instances", []))
if not inst:
print(f" skip svc={svc_id}: нет данных")
skipped += 1
continue
name = svc_to_name.get(svc_id)
if not name:
print(f" skip svc={svc_id}: нет YAML маппинга")
skipped += 1
continue
out_path = f"{DOCS_DIR}/{name}_outputs.md"
if not os.path.exists(out_path):
print(f" skip svc={svc_id} ({name}): нет файла {name}_outputs.md")
skipped += 1
continue
new_section = build_section(inst)
content = open(out_path).read()
if SECTION_MARKER in content:
idx = content.index(SECTION_MARKER)
new_content = content[:idx] + new_section
else:
new_content = content.rstrip("\n") + "\n\n" + new_section
if dry_run:
print(f" dry-run svc={svc_id} ({name}): {out_path}")
print(f" params={list((inst.get('params') or {}).keys())}")
print(f" out_flat_count={len(flatten(inst.get('out') or {}))}")
print(f" vault={inst.get('vault_keys', [])}")
else:
with open(out_path, "w") as f:
f.write(new_content)
print(f" updated svc={svc_id} ({name})")
updated += 1
print(f"\nДone: {updated} updated, {skipped} skipped")
if __name__ == "__main__":
main()