fix: разделение клиентов — сервисы из real API, инстансы/операции из polygon (v1.2.28)
This commit is contained in:
+32
-11
@@ -32,27 +32,48 @@ def get_token():
|
|||||||
return request.cookies.get("token") or current_app.config["NUBES_API_TOKEN"]
|
return request.cookies.get("token") or current_app.config["NUBES_API_TOKEN"]
|
||||||
|
|
||||||
|
|
||||||
def get_client():
|
def _make_client(*, use_polygon):
|
||||||
"""HttpClient с автоопределением стенда.
|
"""Фабрика HttpClient — ЕДИНСТВЕННОЕ место где выбирается endpoint.
|
||||||
|
|
||||||
Если POLYGON_ENDPOINT задан → направить ВСЕ запросы в polygon.
|
Args:
|
||||||
Реальный NUBES_API_TOKEN остаётся нетронутым — polygon его не проверяет.
|
use_polygon: если True и POLYGON_ENDPOINT задан → polygon.
|
||||||
|
Если False → всегда реальный API (для чтения сервисов/инстансов).
|
||||||
|
|
||||||
Иначе:
|
Returns:
|
||||||
- Если NUBES_API_ENDPOINT — известный стенд (STANDS) → detect_endpoint()
|
HttpClient с правильным endpoint и токеном.
|
||||||
- Если кастомный URL → использовать напрямую
|
|
||||||
"""
|
"""
|
||||||
polygon = current_app.config.get("POLYGON_ENDPOINT", "")
|
|
||||||
if polygon:
|
|
||||||
return HttpClient(polygon, get_token())
|
|
||||||
|
|
||||||
token = get_token()
|
token = get_token()
|
||||||
|
|
||||||
|
# Режим полигона — только если разрешено и переменная задана
|
||||||
|
if use_polygon:
|
||||||
|
polygon = current_app.config.get("POLYGON_ENDPOINT", "")
|
||||||
|
if polygon:
|
||||||
|
return HttpClient(polygon, token)
|
||||||
|
|
||||||
|
# Реальный API: автоопределение или NUBES_API_ENDPOINT
|
||||||
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
||||||
if endpoint in STANDS:
|
if endpoint in STANDS:
|
||||||
endpoint = detect_endpoint(token) or endpoint
|
endpoint = detect_endpoint(token) or endpoint
|
||||||
return HttpClient(endpoint, token)
|
return HttpClient(endpoint, token)
|
||||||
|
|
||||||
|
|
||||||
|
def get_client():
|
||||||
|
"""HttpClient для ОПЕРАЦИЙ (create/modify/delete/run/poll).
|
||||||
|
|
||||||
|
Если POLYGON_ENDPOINT задан → polygon.
|
||||||
|
Иначе → автоопределение реального стенда.
|
||||||
|
"""
|
||||||
|
return _make_client(use_polygon=True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_real_client():
|
||||||
|
"""HttpClient для ЧТЕНИЯ (сервисы, список инстансов).
|
||||||
|
|
||||||
|
ВСЕГДА реальный API, даже при POLYGON_ENDPOINT.
|
||||||
|
"""
|
||||||
|
return _make_client(use_polygon=False)
|
||||||
|
|
||||||
|
|
||||||
def get_client_id():
|
def get_client_id():
|
||||||
"""Извлечь ClientID из payload JWT-токена (base64url, без проверки подписи).
|
"""Извлечь ClientID из payload JWT-токена (base64url, без проверки подписи).
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ from routes.api_scenario_defs import bp_defs as api_scenario_defs_bp
|
|||||||
|
|
||||||
# Версия — показывается в топбаре UI. Меняется при КАЖДОМ изменении кода.
|
# Версия — показывается в топбаре UI. Меняется при КАЖДОМ изменении кода.
|
||||||
# Нужна для фильтрации истории (пользователь видит только записи своей версии).
|
# Нужна для фильтрации истории (пользователь видит только записи своей версии).
|
||||||
VERSION = "1.2.27"
|
VERSION = "1.2.28"
|
||||||
|
|
||||||
# Flask-приложение с Jinja2-шаблонами из папки templates/
|
# Flask-приложение с Jinja2-шаблонами из папки templates/
|
||||||
app = Flask(__name__, template_folder="templates", static_folder="static")
|
app = Flask(__name__, template_folder="templates", static_folder="static")
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import json
|
|||||||
import fcntl
|
import fcntl
|
||||||
|
|
||||||
from api.http_client import HttpClient, detect_endpoint, stand_name
|
from api.http_client import HttpClient, detect_endpoint, stand_name
|
||||||
from api.auth import get_token, get_client, get_client_id, get_stand, get_token_info
|
from api.auth import get_token, get_client, get_real_client, get_client_id, get_stand, get_token_info
|
||||||
from api.utils import find_uid, uid_from_location
|
from api.utils import find_uid, uid_from_location
|
||||||
from operations.get_services import get_services, get_service_detail
|
from operations.get_services import get_services, get_service_detail
|
||||||
from operations.get_instances import get_instances
|
from operations.get_instances import get_instances
|
||||||
@@ -103,7 +103,7 @@ def _unique_display_name(client, requested_name):
|
|||||||
@bp.route("/api/services")
|
@bp.route("/api/services")
|
||||||
def api_services():
|
def api_services():
|
||||||
try:
|
try:
|
||||||
raw = get_services(get_client())
|
raw = get_services(get_real_client())
|
||||||
svc_list = [{"svcId": s["svcId"], "svc": s["svc"], "svcExtendedName": s.get("svcExtendedName", "")} for s in raw]
|
svc_list = [{"svcId": s["svcId"], "svc": s["svc"], "svcExtendedName": s.get("svcExtendedName", "")} for s in raw]
|
||||||
svc_list.sort(key=lambda s: s["svcId"])
|
svc_list.sort(key=lambda s: s["svcId"])
|
||||||
return jsonify(svc_list)
|
return jsonify(svc_list)
|
||||||
|
|||||||
+19
-15
@@ -11,7 +11,7 @@ GET /api/operations/<svc_id> — операции и autotest-инста
|
|||||||
from flask import Blueprint, current_app, render_template, request, make_response, jsonify, redirect
|
from flask import Blueprint, current_app, render_template, request, make_response, jsonify, redirect
|
||||||
|
|
||||||
from api.http_client import HttpClient, detect_endpoint, create_client, stand_name
|
from api.http_client import HttpClient, detect_endpoint, create_client, stand_name
|
||||||
from api.auth import get_token, get_client_id, get_token_info, get_token_masked, get_client, get_stand
|
from api.auth import get_token, get_client_id, get_token_info, get_token_masked, get_client, get_real_client, get_stand
|
||||||
from operations.get_instances import get_organization, get_instances
|
from operations.get_instances import get_organization, get_instances
|
||||||
from operations.get_services import get_services, get_service_detail
|
from operations.get_services import get_services, get_service_detail
|
||||||
from operations.service_list import load_service_ids
|
from operations.service_list import load_service_ids
|
||||||
@@ -105,24 +105,26 @@ def index():
|
|||||||
config["service_ids"] = []
|
config["service_ids"] = []
|
||||||
stand = "?"
|
stand = "?"
|
||||||
if active_token:
|
if active_token:
|
||||||
# get_client — учитывает POLYGON_ENDPOINT
|
# Сервисы — ВСЕГДА из реального API (метаданные)
|
||||||
client = get_client()
|
real_client = get_real_client()
|
||||||
|
# Инстансы — из polygon если POLYGON_ENDPOINT задан
|
||||||
|
inst_client = get_client()
|
||||||
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
||||||
stand = get_stand()
|
stand = get_stand()
|
||||||
if client:
|
if real_client:
|
||||||
try:
|
try:
|
||||||
# Организация — инстанс с serviceId=19
|
# Организация — инстанс с serviceId=19 (из реального API)
|
||||||
org = get_organization(client)
|
org = get_organization(real_client)
|
||||||
|
|
||||||
# Все сервисы — сортировка по svcId
|
# Все сервисы — из реального API
|
||||||
raw_svc = get_services(client)
|
raw_svc = get_services(real_client)
|
||||||
services = sorted(raw_svc, key=lambda s: (s.get("svcId", 0), s.get("svc", "")))
|
services = sorted(raw_svc, key=lambda s: (s.get("svcId", 0), s.get("svc", "")))
|
||||||
|
|
||||||
# Инфраструктурные инстансы — только определённые serviceId
|
# Инфраструктурные инстансы — из polygon или реального API
|
||||||
# 19=Org, 21=vDC, 22=NSX-T, 25=External IP, 26=vApp, 29=vDC Group
|
# 19=Org, 21=vDC, 22=NSX-T, 25=External IP, 26=vApp, 29=vDC Group
|
||||||
# 2=Template, 12=S3, 110=?, 150=K8s
|
# 2=Template, 12=S3, 110=?, 150=K8s
|
||||||
infra_ids = {2, 12, 21, 22, 25, 26, 29, 110, 150}
|
infra_ids = {2, 12, 21, 22, 25, 26, 29, 110, 150}
|
||||||
raw_inst = get_instances(client)
|
raw_inst = get_instances(inst_client)
|
||||||
instances = [i for i in raw_inst
|
instances = [i for i in raw_inst
|
||||||
if i.get("explainedStatus") not in ("deleted", "not created")
|
if i.get("explainedStatus") not in ("deleted", "not created")
|
||||||
and i.get("serviceId") in infra_ids]
|
and i.get("serviceId") in infra_ids]
|
||||||
@@ -168,20 +170,22 @@ def api_operations(svc_id):
|
|||||||
active_token = user_token or env_token
|
active_token = user_token or env_token
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# get_client — учитывает POLYGON_ENDPOINT
|
# Сервисы — ВСЕГДА из реального API (метаданные)
|
||||||
client = get_client()
|
real_client = get_real_client()
|
||||||
|
# Инстансы — из polygon если POLYGON_ENDPOINT задан
|
||||||
|
inst_client = get_client()
|
||||||
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
endpoint = current_app.config["NUBES_API_ENDPOINT"]
|
||||||
|
|
||||||
# Детали сервиса: список операций (modify, delete, suspend, ...)
|
# Детали сервиса: список операций (modify, delete, suspend, ...)
|
||||||
detail = get_service_detail(client, svc_id)
|
detail = get_service_detail(real_client, svc_id)
|
||||||
ops = detail.get("operations", [])
|
ops = detail.get("operations", [])
|
||||||
|
|
||||||
# Трекер: наши autotest-инстансы (изолирован по пользователю и стенду)
|
# Трекер: наши autotest-инстансы (изолирован по пользователю и стенду)
|
||||||
tracked = tracker_list(get_client_id(), stand_name(endpoint))
|
tracked = tracker_list(get_client_id(), stand_name(endpoint))
|
||||||
tracked_by_uid = {t["instanceUid"]: t for t in tracked if t["svcId"] == svc_id}
|
tracked_by_uid = {t["instanceUid"]: t for t in tracked if t["svcId"] == svc_id}
|
||||||
|
|
||||||
# Все инстансы из облака
|
# Все инстансы — из polygon или реального API
|
||||||
instances = get_instances(client)
|
instances = get_instances(inst_client)
|
||||||
nubes_uids = {i["instanceUid"] for i in instances}
|
nubes_uids = {i["instanceUid"] for i in instances}
|
||||||
|
|
||||||
svc_instances = []
|
svc_instances = []
|
||||||
|
|||||||
Reference in New Issue
Block a user