v1.2.16: save full instance metadata (instance_meta JSONB)

init_db.py: ALTER TABLE runs ADD instance_meta JSONB
save_run.py: +instance_meta parameter → JSONB insert
api_test.py: _finish_op fetches GET /instances/{uid} after poll, saves all fields
scenario.py: run_scenario same — per-step instance metadata
Excludes: instanceUid, displayName, svc, serviceId, explainedStatus (already in other columns)
This commit is contained in:
2026-07-31 14:19:29 +04:00
parent 0180f3cb3f
commit 82a3be2067
5 changed files with 32 additions and 7 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ from routes.api_scenario_run import bp_run as api_scenario_run_bp
from routes.api_scenario_defs import bp_defs as api_scenario_defs_bp from routes.api_scenario_defs import bp_defs as api_scenario_defs_bp
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI. # Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
VERSION = "1.2.15" VERSION = "1.2.16"
app = Flask(__name__, template_folder="templates", static_folder="static") app = Flask(__name__, template_folder="templates", static_folder="static")
app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc") app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc")
+1
View File
@@ -59,6 +59,7 @@ ALTER TABLE runs ADD COLUMN IF NOT EXISTS user_email VARCHAR(128);
ALTER TABLE runs ADD COLUMN IF NOT EXISTS app_version VARCHAR(16); ALTER TABLE runs ADD COLUMN IF NOT EXISTS app_version VARCHAR(16);
ALTER TABLE runs ADD COLUMN IF NOT EXISTS scenario_run_id INTEGER; ALTER TABLE runs ADD COLUMN IF NOT EXISTS scenario_run_id INTEGER;
ALTER TABLE runs ADD COLUMN IF NOT EXISTS step_number INTEGER; ALTER TABLE runs ADD COLUMN IF NOT EXISTS step_number INTEGER;
ALTER TABLE runs ADD COLUMN IF NOT EXISTS instance_meta JSONB;
""" """
# Таблица сценариев — один запуск = одна строка # Таблица сценариев — один запуск = одна строка
+6 -4
View File
@@ -9,9 +9,10 @@ from db.pool import get_conn, put_conn
def save_run(client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id, def save_run(client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id,
op_uid, instance_uid, display_name, status, duration_sec, op_uid, instance_uid, display_name, status, duration_sec,
error_log, params, stages, app_version, error_log, params, stages, app_version,
scenario_run_id=None, step_number=None): scenario_run_id=None, step_number=None, instance_meta=None):
"""Сохранить один запуск в таблицу runs. """Сохранить один запуск в таблицу runs.
Опционально: scenario_run_id + step_number для шагов сценария.""" Опционально: scenario_run_id + step_number для шагов сценария.
instance_meta — JSONB с полной информацией об инстансе."""
conn = get_conn() conn = get_conn()
if not conn: if not conn:
print("[DB] save_run SKIP: no connection", flush=True) print("[DB] save_run SKIP: no connection", flush=True)
@@ -23,8 +24,8 @@ def save_run(client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id,
INSERT INTO runs (client_id, stand, user_email, svc_id, svc_name, INSERT INTO runs (client_id, stand, user_email, svc_id, svc_name,
op_name, svc_op_id, op_uid, instance_uid, display_name, op_name, svc_op_id, op_uid, instance_uid, display_name,
status, duration_sec, error_log, params, stages, app_version, status, duration_sec, error_log, params, stages, app_version,
scenario_run_id, step_number) scenario_run_id, step_number, instance_meta)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", ( """, (
client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id, client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id,
op_uid, instance_uid, display_name, status, duration_sec, op_uid, instance_uid, display_name, status, duration_sec,
@@ -33,6 +34,7 @@ def save_run(client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id,
json.dumps(stages) if stages else None, json.dumps(stages) if stages else None,
app_version, app_version,
scenario_run_id, step_number, scenario_run_id, step_number,
json.dumps(instance_meta) if instance_meta else None,
)) ))
conn.commit() conn.commit()
cur.close() cur.close()
+12 -1
View File
@@ -177,12 +177,23 @@ def run_scenario(client, steps, client_id, stand, user_email, app_version, scena
# 7. Сохранить финальный результат # 7. Сохранить финальный результат
try: try:
# Получить полную информацию об инстансе
instance_meta = None
try:
inst_data = client.get(f"/instances/{instance_uid}")
inst = inst_data.get("instance", {}) if isinstance(inst_data, dict) else {}
if inst:
instance_meta = {k: v for k, v in inst.items()
if k not in ('instanceUid', 'displayName', 'svc', 'serviceId', 'explainedStatus')}
except Exception:
pass
save_run(client_id, stand, user_email, save_run(client_id, stand, user_email,
svc_id, svc_final, op_name, svc_op_id, svc_id, svc_final, op_name, svc_op_id,
op_uid, instance_uid, step_display, op_uid, instance_uid, step_display,
step_status, step_duration, step_error, step_status, step_duration, step_error,
resolved_params, step_stages, app_version, resolved_params, step_stages, app_version,
scenario_run_id, step_num) scenario_run_id, step_num,
instance_meta=instance_meta)
except Exception as e: except Exception as e:
print(f"[SCENARIO] save_run failed for step {step_num}: {e}", flush=True) print(f"[SCENARIO] save_run failed for step {step_num}: {e}", flush=True)
+12 -1
View File
@@ -319,6 +319,16 @@ def _finish_op(client, op_uid, instance_uid, svc_id, display_name, op_name, svc_
# Сохранить в БД # Сохранить в БД
try: try:
from db.save_run import save_run from db.save_run import save_run
# Получить полную информацию об инстансе
instance_meta = None
try:
inst_data = client.get(f"/instances/{instance_uid}")
inst = inst_data.get("instance", {}) if isinstance(inst_data, dict) else {}
if inst:
instance_meta = {k: v for k, v in inst.items()
if k not in ('instanceUid', 'displayName', 'svc', 'serviceId', 'explainedStatus')}
except Exception:
pass
saved_params = redact_params(params or {}) saved_params = redact_params(params or {})
save_run(client_id, stand, user_email, save_run(client_id, stand, user_email,
svc_id, poll_result["svc"], op_name, svc_op_id, svc_id, poll_result["svc"], op_name, svc_op_id,
@@ -326,7 +336,8 @@ def _finish_op(client, op_uid, instance_uid, svc_id, display_name, op_name, svc_
poll_result["status"], poll_result["status"],
poll_result["duration"], poll_result["duration"],
poll_result["error_log"], poll_result["error_log"],
saved_params, poll_result["stages"], app_version) saved_params, poll_result["stages"], app_version,
instance_meta=instance_meta)
except Exception as e: except Exception as e:
import traceback import traceback
print(f"[DB] save_run FAILED: {e}", flush=True) print(f"[DB] save_run FAILED: {e}", flush=True)