84 lines
3.3 KiB
Python
84 lines
3.3 KiB
Python
# 2026-03-18
|
|
# funcs_list.py — HTTP-функция, возвращает список всех функций пользователя.
|
|
# Вызывает внутренний REST API оператора (http://sless-operator.sless.svc.cluster.local:9090).
|
|
# Объединяет данные функций и их триггеров в один ответ.
|
|
#
|
|
# Env vars (обязательные):
|
|
# SLESS_API_URL — URL оператора внутри кластера
|
|
# SLESS_NAMESPACE — namespace пользователя (sless-{hex16})
|
|
# SLESS_TOKEN — JWT токен для авторизации в /v1/ API
|
|
#
|
|
# Поля в ответе:
|
|
# name, runtime, phase, image_ref, message — из /v1/namespaces/{ns}/functions
|
|
# triggers[].type/enabled/active/url — из /v1/namespaces/{ns}/triggers
|
|
#
|
|
# Что ПОКА не возвращается (фиксировано оператором):
|
|
# created_at — metav1.CreationTimestamp, не включён в fnToResponse (нужно v0.1.32+)
|
|
# last_built_at — FunctionStatus.LastBuiltAt, не включён в fnToResponse (нужно v0.1.32+)
|
|
|
|
import os
|
|
import json
|
|
import requests
|
|
|
|
|
|
def list_all(event):
|
|
api_url = os.environ["SLESS_API_URL"].rstrip("/")
|
|
namespace = os.environ["SLESS_NAMESPACE"]
|
|
token = os.environ["SLESS_TOKEN"]
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
fns_resp = requests.get(
|
|
f"{api_url}/v1/namespaces/{namespace}/functions",
|
|
headers=headers,
|
|
timeout=10,
|
|
)
|
|
fns_resp.raise_for_status()
|
|
functions = fns_resp.json()
|
|
|
|
trs_resp = requests.get(
|
|
f"{api_url}/v1/namespaces/{namespace}/triggers",
|
|
headers=headers,
|
|
timeout=10,
|
|
)
|
|
trs_resp.raise_for_status()
|
|
triggers = trs_resp.json()
|
|
|
|
# Индексируем триггеры по имени функции (поле "function" = functionRef).
|
|
triggers_by_fn = {}
|
|
for tr in triggers:
|
|
fn_name = tr.get("function") or tr.get("functionRef")
|
|
if fn_name:
|
|
triggers_by_fn.setdefault(fn_name, []).append(tr)
|
|
|
|
result = []
|
|
for fn in functions:
|
|
name = fn["name"]
|
|
fn_triggers = [
|
|
{
|
|
"name": tr.get("name"),
|
|
"type": tr.get("type"),
|
|
"enabled": tr.get("enabled", True),
|
|
"active": tr.get("active", False),
|
|
"url": tr.get("url", ""),
|
|
"schedule": tr.get("schedule", ""),
|
|
}
|
|
for tr in triggers_by_fn.get(name, [])
|
|
]
|
|
|
|
result.append({
|
|
"name": name,
|
|
"runtime": fn.get("runtime"),
|
|
"phase": fn.get("phase"),
|
|
# active = у функции есть хотя бы один включённый и активный триггер
|
|
"active": any(t["enabled"] and t["active"] for t in fn_triggers),
|
|
"image_ref": fn.get("image_ref", ""),
|
|
"message": fn.get("message", ""),
|
|
"triggers": fn_triggers,
|
|
# TODO: добавить created_at и last_built_at после обновления оператора до v0.1.32+
|
|
})
|
|
|
|
# Сортируем: сначала активные, потом по имени
|
|
result.sort(key=lambda f: (not f["active"], f["name"]))
|
|
|
|
return {"functions": result, "count": len(result)}
|