From f97fd8a744ede0bab3143fee71d4e6c88a119d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 4 May 2026 07:03:43 +0400 Subject: [PATCH] =?UTF-8?q?v1.3.49:=20edit=20modal=20=E2=80=94=20remove=20?= =?UTF-8?q?mode=20toggle,=20show=20archive=20name,=20timeout-only=20save;?= =?UTF-8?q?=20add=20PUT=20/functions/:name/timeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- console/deploy/console.yaml | 2 +- console/internal/api/handlers.go | 45 ++++++++++++++++++++++++++++++++ console/ui/index.html | 12 ++++----- console/ui/js/functions.js | 9 +++++++ 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/console/deploy/console.yaml b/console/deploy/console.yaml index 58f69da..548f876 100644 --- a/console/deploy/console.yaml +++ b/console/deploy/console.yaml @@ -52,7 +52,7 @@ spec: serviceAccountName: fission-console containers: - name: console - image: naeel/fission-console:v1.3.48 + image: naeel/fission-console:v1.3.49 imagePullPolicy: Always ports: - containerPort: 8090 diff --git a/console/internal/api/handlers.go b/console/internal/api/handlers.go index 65d48bf..2d30f3a 100644 --- a/console/internal/api/handlers.go +++ b/console/internal/api/handlers.go @@ -310,6 +310,12 @@ func (s *Server) handleFunctionsAction(w http.ResponseWriter, r *http.Request) { return } + // /functions/:name/timeout — обновление только таймаута (без замены архива/кода) + if len(parts) == 2 && parts[1] == "timeout" && r.Method == http.MethodPut { + s.handleUpdateFunctionTimeout(w, r, name) + return + } + // /functions/:name/archive — обновление через zip-архив if len(parts) == 2 && parts[1] == "archive" && r.Method == http.MethodPut { s.handleUpdateFunctionArchive(w, r, name) @@ -760,6 +766,45 @@ func (s *Server) handleUpdateFunctionCode(w http.ResponseWriter, r *http.Request }) } +// handleUpdateFunctionTimeout обновляет только spec.functionTimeout функции (без замены кода/архива). +func (s *Server) handleUpdateFunctionTimeout(w http.ResponseWriter, r *http.Request, name string) { + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + ns := s.userNS(r) + + var req struct { + Timeout int64 `json:"timeout"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("decode request: %v", err)) + return + } + timeout := normalizeFunctionTimeout(req.Timeout) + + fn, err := s.dyn.Resource(fission.FunctionGVR).Namespace(ns).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + writeJSONError(w, http.StatusBadGateway, fmt.Sprintf("get function %q: %v", name, err)) + return + } + if err := unstructured.SetNestedField(fn.Object, timeout, "spec", "functionTimeout"); err != nil { + writeJSONError(w, http.StatusInternalServerError, fmt.Sprintf("set timeout: %v", err)) + return + } + now := time.Now().UTC().Format(time.RFC3339) + ann := fn.GetAnnotations() + if ann == nil { + ann = map[string]string{} + } + ann[functionUpdatedAtAnnotation] = now + fn.SetAnnotations(ann) + + if _, err := s.dyn.Resource(fission.FunctionGVR).Namespace(ns).Update(ctx, fn, metav1.UpdateOptions{}); err != nil { + writeJSONError(w, http.StatusBadGateway, fmt.Sprintf("update function %q: %v", name, err)) + return + } + writeAnyJSON(w, http.StatusOK, map[string]any{"updated": true, "timeout": timeout}) +} + // handleInvokeFunction вызывает функцию через Fission router. // Определяет реальный URL из HTTPTrigger, выбирает метод (POST/GET). func (s *Server) handleInvokeFunction(w http.ResponseWriter, r *http.Request, name string) { diff --git a/console/ui/index.html b/console/ui/index.html index 1fef885..1cb1d14 100644 --- a/console/ui/index.html +++ b/console/ui/index.html @@ -102,7 +102,7 @@
NUBES
FISSION CONSOLE
-
v1.3.48
+
v1.3.49
@@ -352,10 +352,6 @@
-
- - -
@@ -367,6 +363,10 @@
diff --git a/console/ui/js/functions.js b/console/ui/js/functions.js index 10b0942..65db716 100644 --- a/console/ui/js/functions.js +++ b/console/ui/js/functions.js @@ -149,6 +149,10 @@ async function openEdit(name) { // Сбрасываем режим: source_type из API (code / archive) if (fn.source_type === 'archive') { setCodeMode('e', 'archive'); + var archiveNameEl = document.getElementById('e-archive-name'); + if (archiveNameEl) archiveNameEl.textContent = fn.package || 'архив'; + var archiveFile = document.getElementById('e-archive-file'); + if (archiveFile) archiveFile.value = ''; } else { setCodeMode('e', 'code'); } @@ -205,6 +209,11 @@ async function submitEdit() { var resp = await fetch(API_BASE + '/functions/' + encodeURIComponent(name) + '/archive', { method: 'PUT', headers: authHeaders(), body: fd }); if (!resp.ok) { var e = await resp.json().catch(() => ({})); throw new Error(e.error || resp.statusText); } + } else if (isArchiveMode) { + // Архив не заменяется — обновляем только timeout + await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/timeout', 'PUT', { + timeout: parseTimeout(document.getElementById('e-timeout').value) + }); } else { await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/code', 'PUT', { code: document.getElementById('e-code').value,