feat: logs modal + ESC close + /functions/:name/logs endpoint (v1.3.61)
This commit is contained in:
@@ -25,6 +25,7 @@ import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// validFuncName — RFC 1123 subdomain label: строчные буквы+цифры+дефис, без дефиса в начале/конце.
|
||||
@@ -332,6 +333,12 @@ func (s *Server) handleFunctionsAction(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// /functions/:name/logs — логи подов функции
|
||||
if len(parts) == 2 && parts[1] == "logs" && r.Method == http.MethodGet {
|
||||
s.handleGetFunctionLogs(w, r, name)
|
||||
return
|
||||
}
|
||||
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
@@ -1613,3 +1620,57 @@ func (s *Server) handleUpdateFunctionArchive(w http.ResponseWriter, r *http.Requ
|
||||
"source_type": "archive",
|
||||
})
|
||||
}
|
||||
|
||||
// handleGetFunctionLogs возвращает логи пода функции (последние 100 строк).
|
||||
// Ищет под по лейблу functionName=<name> в namespace пользователя.
|
||||
func (s *Server) handleGetFunctionLogs(w http.ResponseWriter, r *http.Request, name string) {
|
||||
ns := s.userNS(r)
|
||||
ctx := r.Context()
|
||||
|
||||
if s.kube == nil {
|
||||
writeJSONError(w, http.StatusServiceUnavailable, "kubernetes client not available")
|
||||
return
|
||||
}
|
||||
|
||||
labelSelector := "functionName=" + name
|
||||
pods, err := s.kube.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{
|
||||
LabelSelector: labelSelector,
|
||||
})
|
||||
if err != nil {
|
||||
writeJSONError(w, http.StatusInternalServerError, "list pods: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(pods.Items) == 0 {
|
||||
writeAnyJSON(w, http.StatusOK, map[string]any{
|
||||
"logs": "(нет запущенных подов для функции " + name + ")",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var allLogs strings.Builder
|
||||
tailLines := int64(100)
|
||||
for _, pod := range pods.Items {
|
||||
req := s.kube.CoreV1().Pods(ns).GetLogs(pod.Name, &corev1.PodLogOptions{
|
||||
Container: "user-container",
|
||||
TailLines: &tailLines,
|
||||
})
|
||||
rc, err := req.Stream(ctx)
|
||||
if err != nil {
|
||||
allLogs.WriteString("[" + pod.Name + ": ошибка чтения логов: " + err.Error() + "]\n")
|
||||
continue
|
||||
}
|
||||
data, _ := io.ReadAll(rc)
|
||||
rc.Close()
|
||||
if allLogs.Len() > 0 {
|
||||
allLogs.WriteString("\n--- " + pod.Name + " ---\n")
|
||||
} else {
|
||||
allLogs.WriteString("--- " + pod.Name + " ---\n")
|
||||
}
|
||||
allLogs.Write(data)
|
||||
}
|
||||
|
||||
writeAnyJSON(w, http.StatusOK, map[string]any{
|
||||
"logs": allLogs.String(),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user