v1.3.50: fix archive fn — entrypoint update in edit, store/show archive filename

This commit is contained in:
“Naeel”
2026-05-04 08:14:19 +04:00
parent f97fd8a744
commit 2fdba29f79
4 changed files with 49 additions and 21 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ spec:
serviceAccountName: fission-console serviceAccountName: fission-console
containers: containers:
- name: console - name: console
image: naeel/fission-console:v1.3.49 image: naeel/fission-console:v1.3.50
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 8090 - containerPort: 8090
+41 -15
View File
@@ -618,26 +618,31 @@ func (s *Server) handleGetFunction(w http.ResponseWriter, r *http.Request, name
// Читаем source-type аннотацию (code / archive) // Читаем source-type аннотацию (code / archive)
sourceType := "code" sourceType := "code"
archiveFilename := ""
if ann := fn.GetAnnotations(); ann != nil { if ann := fn.GetAnnotations(); ann != nil {
if v := ann[fissionSourceTypeAnnotation]; v != "" { if v := ann[fissionSourceTypeAnnotation]; v != "" {
sourceType = v sourceType = v
} }
if v := ann["fission-console/archive-filename"]; v != "" {
archiveFilename = v
}
} }
writeAnyJSON(w, http.StatusOK, map[string]any{ writeAnyJSON(w, http.StatusOK, map[string]any{
"name": name, "name": name,
"namespace": ns, "namespace": ns,
"environment": environment, "environment": environment,
"package": packageName, "package": packageName,
"entrypoint": entrypoint, "entrypoint": entrypoint,
"timeout": functionTimeout, "timeout": functionTimeout,
"created_at": functionTimestampResponse(fn)["created_at"], "created_at": functionTimestampResponse(fn)["created_at"],
"updated_at": functionTimestampResponse(fn)["updated_at"], "updated_at": functionTimestampResponse(fn)["updated_at"],
"code": code, "code": code,
"source_type": sourceType, "source_type": sourceType,
"route": route, "archive_filename": archiveFilename,
"methods": methods, "route": route,
"raw": fn.Object, "methods": methods,
"raw": fn.Object,
}) })
} }
@@ -773,7 +778,8 @@ func (s *Server) handleUpdateFunctionTimeout(w http.ResponseWriter, r *http.Requ
ns := s.userNS(r) ns := s.userNS(r)
var req struct { var req struct {
Timeout int64 `json:"timeout"` Timeout int64 `json:"timeout"`
Entrypoint string `json:"entrypoint"`
} }
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("decode request: %v", err)) writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("decode request: %v", err))
@@ -790,6 +796,9 @@ func (s *Server) handleUpdateFunctionTimeout(w http.ResponseWriter, r *http.Requ
writeJSONError(w, http.StatusInternalServerError, fmt.Sprintf("set timeout: %v", err)) writeJSONError(w, http.StatusInternalServerError, fmt.Sprintf("set timeout: %v", err))
return return
} }
if req.Entrypoint != "" {
_ = unstructured.SetNestedField(fn.Object, req.Entrypoint, "spec", "package", "functionName")
}
now := time.Now().UTC().Format(time.RFC3339) now := time.Now().UTC().Format(time.RFC3339)
ann := fn.GetAnnotations() ann := fn.GetAnnotations()
if ann == nil { if ann == nil {
@@ -1310,7 +1319,7 @@ func (s *Server) handleCreateFunctionFromArchive(w http.ResponseWriter, r *http.
lang := strings.TrimSpace(r.FormValue("language")) lang := strings.TrimSpace(r.FormValue("language"))
envName := strings.TrimSpace(r.FormValue("environment")) envName := strings.TrimSpace(r.FormValue("environment"))
f, _, err := r.FormFile("archive") f, fhCreate, err := r.FormFile("archive")
if err != nil { if err != nil {
writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("archive file required: %v", err)) writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("archive file required: %v", err))
return return
@@ -1321,6 +1330,10 @@ func (s *Server) handleCreateFunctionFromArchive(w http.ResponseWriter, r *http.
writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("read archive: %v", err)) writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("read archive: %v", err))
return return
} }
archiveFilenameCreate := ""
if fhCreate != nil {
archiveFilenameCreate = fhCreate.Filename
}
nsCtx, nsCancel := context.WithTimeout(r.Context(), 60*time.Second) nsCtx, nsCancel := context.WithTimeout(r.Context(), 60*time.Second)
defer nsCancel() defer nsCancel()
@@ -1407,6 +1420,9 @@ func (s *Server) handleCreateFunctionFromArchive(w http.ResponseWriter, r *http.
functionCreatedAtAnnotation: now.Format(time.RFC3339), functionCreatedAtAnnotation: now.Format(time.RFC3339),
functionUpdatedAtAnnotation: now.Format(time.RFC3339), functionUpdatedAtAnnotation: now.Format(time.RFC3339),
} }
if archiveFilenameCreate != "" {
fnAnnotations["fission-console/archive-filename"] = archiveFilenameCreate
}
if ttl := r.FormValue("ttl"); ttl != "" { if ttl := r.FormValue("ttl"); ttl != "" {
if expiresAt, ttlErr := parseTTL(ttl); ttlErr == nil { if expiresAt, ttlErr := parseTTL(ttl); ttlErr == nil {
fnAnnotations["fission-console/expires-at"] = expiresAt.UTC().Format(time.RFC3339) fnAnnotations["fission-console/expires-at"] = expiresAt.UTC().Format(time.RFC3339)
@@ -1546,12 +1562,22 @@ func (s *Server) handleUpdateFunctionArchive(w http.ResponseWriter, r *http.Requ
} }
_ = unstructured.SetNestedField(fn.Object, timeout, "spec", "functionTimeout") _ = unstructured.SetNestedField(fn.Object, timeout, "spec", "functionTimeout")
// Обновляем entrypoint если передан
if ep := strings.TrimSpace(r.FormValue("entrypoint")); ep != "" {
_ = unstructured.SetNestedField(fn.Object, ep, "spec", "package", "functionName")
}
fnAnnotations := fn.GetAnnotations() fnAnnotations := fn.GetAnnotations()
if fnAnnotations == nil { if fnAnnotations == nil {
fnAnnotations = map[string]string{} fnAnnotations = map[string]string{}
} }
fnAnnotations[fissionSourceTypeAnnotation] = "archive" fnAnnotations[fissionSourceTypeAnnotation] = "archive"
fnAnnotations[functionUpdatedAtAnnotation] = time.Now().UTC().Format(time.RFC3339) fnAnnotations[functionUpdatedAtAnnotation] = time.Now().UTC().Format(time.RFC3339)
if fh, fhErr := r.MultipartForm.File["archive"]; fhErr == false || len(fh) > 0 {
if files := r.MultipartForm.File["archive"]; len(files) > 0 && files[0].Filename != "" {
fnAnnotations["fission-console/archive-filename"] = files[0].Filename
}
}
fn.SetAnnotations(fnAnnotations) fn.SetAnnotations(fnAnnotations)
if err := unstructured.SetNestedField(fn.Object, map[string]any{ if err := unstructured.SetNestedField(fn.Object, map[string]any{
+2 -2
View File
@@ -102,7 +102,7 @@
<div class="nubes">NUBES</div> <div class="nubes">NUBES</div>
<div class="product">FISSION CONSOLE</div> <div class="product">FISSION CONSOLE</div>
</div> </div>
<div style="font-size:0.65rem; color:var(--text-secondary); margin-left:10px; align-self:center; opacity:0.7;">v1.3.49</div> <div style="font-size:0.65rem; color:var(--text-secondary); margin-left:10px; align-self:center; opacity:0.7;">v1.3.50</div>
</div> </div>
<div class="row" style="margin:0;"> <div class="row" style="margin:0;">
<button class="btn ghost" onclick="reloadAll()">Refresh</button> <button class="btn ghost" onclick="reloadAll()">Refresh</button>
@@ -462,7 +462,7 @@
</div> </div>
<div class="actions" style="justify-content:space-between; align-items:center;"> <div class="actions" style="justify-content:space-between; align-items:center;">
<span style="font-size:0.75rem; color:var(--text-secondary);">v1.3.49</span> <span style="font-size:0.75rem; color:var(--text-secondary);">v1.3.50</span>
<button class="btn ghost" onclick="closeHelp()">Закрыть</button> <button class="btn ghost" onclick="closeHelp()">Закрыть</button>
</div> </div>
</div> </div>
+5 -3
View File
@@ -150,7 +150,7 @@ async function openEdit(name) {
if (fn.source_type === 'archive') { if (fn.source_type === 'archive') {
setCodeMode('e', 'archive'); setCodeMode('e', 'archive');
var archiveNameEl = document.getElementById('e-archive-name'); var archiveNameEl = document.getElementById('e-archive-name');
if (archiveNameEl) archiveNameEl.textContent = fn.package || 'архив'; if (archiveNameEl) archiveNameEl.textContent = fn.archive_filename || fn.package || 'архив';
var archiveFile = document.getElementById('e-archive-file'); var archiveFile = document.getElementById('e-archive-file');
if (archiveFile) archiveFile.value = ''; if (archiveFile) archiveFile.value = '';
} else { } else {
@@ -205,14 +205,16 @@ async function submitEdit() {
// Обновляем через архив // Обновляем через архив
var fd = new FormData(); var fd = new FormData();
fd.append('timeout', String(parseTimeout(document.getElementById('e-timeout').value))); fd.append('timeout', String(parseTimeout(document.getElementById('e-timeout').value)));
fd.append('entrypoint', document.getElementById('e-entry').value.trim());
fd.append('archive', archiveFile); fd.append('archive', archiveFile);
var resp = await fetch(API_BASE + '/functions/' + encodeURIComponent(name) + '/archive', var resp = await fetch(API_BASE + '/functions/' + encodeURIComponent(name) + '/archive',
{ method: 'PUT', headers: authHeaders(), body: fd }); { method: 'PUT', headers: authHeaders(), body: fd });
if (!resp.ok) { var e = await resp.json().catch(() => ({})); throw new Error(e.error || resp.statusText); } if (!resp.ok) { var e = await resp.json().catch(() => ({})); throw new Error(e.error || resp.statusText); }
} else if (isArchiveMode) { } else if (isArchiveMode) {
// Архив не заменяется — обновляем только timeout // Архив не заменяется — обновляем только timeout + entrypoint
await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/timeout', 'PUT', { await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/timeout', 'PUT', {
timeout: parseTimeout(document.getElementById('e-timeout').value) timeout: parseTimeout(document.getElementById('e-timeout').value),
entrypoint: document.getElementById('e-entry').value.trim()
}); });
} else { } else {
await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/code', 'PUT', { await requestJSON(API_BASE + '/functions/' + encodeURIComponent(name) + '/code', 'PUT', {