Opus review fixes: - executor.py: tracker_add inside executor after instance_uid, before params/run (A3, orphan protection) - executor.py: descr parameter (version/context instead of hardcoded) - api_test.py: pass client_id/stand/descr, remove duplicate tracker_add - scenario.py: pass client_id/stand/descr with scenario context - params-render.js: fix labelCls ReferenceError in renderMapFixedRow (pre-existing bug) - index.html: params-render.js already before operations.js (verified)
89 lines
4.3 KiB
Python
89 lines
4.3 KiB
Python
"""
|
||
Единый executor операции Nubes.
|
||
|
||
Делает всё до /run включительно. НЕ поллит.
|
||
Вызывает tracker_add для create сразу после получения instance_uid (защита от сирот).
|
||
Используется api_test.py (ручной) и scenario.py (сценарный).
|
||
"""
|
||
|
||
from api.utils import find_uid, uid_from_location
|
||
from operations.terraform import send_params_terraform
|
||
from operations.tracker import add as tracker_add
|
||
|
||
|
||
def execute_operation(client, service_id, operation, instance_uid, params,
|
||
svc_op_id=None, display_name=None, descr=None,
|
||
client_id="", stand=""):
|
||
"""Запустить операцию и вернуть результат.
|
||
|
||
Args:
|
||
client: HttpClient
|
||
service_id: int — ID сервиса
|
||
operation: str — create/delete/modify/suspend/resume/redeploy
|
||
instance_uid: str|None — UUID существующего инстанса (None для create)
|
||
params: dict — {numeric_param_id: value}
|
||
svc_op_id: int|None — svcOperationId (игнорируется для create)
|
||
display_name: str|None — displayName (только для create)
|
||
descr: str|None — описание инстанса
|
||
client_id: str — для tracker_add
|
||
stand: str — для tracker_add
|
||
|
||
Returns:
|
||
dict {ok, error, failed_step, instance_uid, op_uid, display_name}
|
||
ok=True при успехе, ok=False при ошибке с failed_step.
|
||
"""
|
||
is_create = (operation == "create")
|
||
|
||
# --- Шаг 1: POST /instances (только create) ---
|
||
if is_create:
|
||
if not display_name:
|
||
display_name = f"autotest-{service_id}"
|
||
if not descr:
|
||
descr = "created by autotest"
|
||
payload = {"serviceId": service_id, "displayName": display_name, "descr": descr}
|
||
try:
|
||
resp = client.post("/instances", payload)
|
||
except Exception as e:
|
||
return {"ok": False, "error": str(e), "failed_step": "instances",
|
||
"instance_uid": None, "op_uid": None, "display_name": display_name}
|
||
instance_uid = resp.get("instanceUid") or find_uid(resp) or uid_from_location(resp.get("_location", ""))
|
||
if not instance_uid:
|
||
return {"ok": False, "error": "No instanceUid in response", "failed_step": "instances",
|
||
"instance_uid": None, "op_uid": None, "display_name": display_name}
|
||
|
||
# tracker_add СРАЗУ после instance_uid, до params/run — защита от сирот
|
||
try:
|
||
tracker_add(client_id, stand, instance_uid, service_id, display_name)
|
||
except Exception:
|
||
pass # не ронять операцию из-за трекера
|
||
|
||
# --- Шаг 2: POST /instanceOperations ---
|
||
if is_create:
|
||
op_payload = {"instanceUid": instance_uid, "operation": operation}
|
||
else:
|
||
op_payload = {"instanceUid": instance_uid, "svcOperationId": svc_op_id, "operation": operation}
|
||
try:
|
||
op_resp = client.post("/instanceOperations", op_payload)
|
||
except Exception as e:
|
||
return {"ok": False, "error": str(e), "failed_step": "instanceOperations",
|
||
"instance_uid": instance_uid, "op_uid": None, "display_name": display_name}
|
||
op_uid = op_resp.get("instanceOperationUid") or find_uid(op_resp) or uid_from_location(op_resp.get("_location", ""))
|
||
if not op_uid:
|
||
return {"ok": False, "error": "No opUid in response", "failed_step": "instanceOperations",
|
||
"instance_uid": instance_uid, "op_uid": None, "display_name": display_name}
|
||
|
||
# --- Шаг 3-6: Параметры + run ---
|
||
try:
|
||
send_params_terraform(client, op_uid, params)
|
||
except Exception as e:
|
||
return {"ok": False, "error": str(e), "failed_step": "params",
|
||
"instance_uid": instance_uid, "op_uid": op_uid, "display_name": display_name}
|
||
try:
|
||
client.post(f"/instanceOperations/{op_uid}/run")
|
||
except Exception as e:
|
||
return {"ok": False, "error": str(e), "failed_step": "run",
|
||
"instance_uid": instance_uid, "op_uid": op_uid, "display_name": display_name}
|
||
|
||
return {"ok": True, "error": None, "failed_step": None,
|
||
"instance_uid": instance_uid, "op_uid": op_uid, "display_name": display_name}
|