mirror of
https://github.com/portainer/portainer.git
synced 2025-07-19 05:19:39 +02:00
feat: add warning events count next to the status badge (#828)
This commit is contained in:
parent
f4df51884c
commit
1332f718ae
18 changed files with 120 additions and 37 deletions
|
@ -22,6 +22,7 @@ import (
|
|||
// @produce json
|
||||
// @param id path int true "Environment identifier"
|
||||
// @param withResourceQuota query boolean true "When set to true, include the resource quota information as part of the Namespace information. Default is false"
|
||||
// @param withUnhealthyEvents query boolean true "When set to true, include the unhealthy events information as part of the Namespace information. Default is false"
|
||||
// @success 200 {array} portainer.K8sNamespaceInfo "Success"
|
||||
// @failure 400 "Invalid request payload, such as missing required fields or fields not meeting validation criteria."
|
||||
// @failure 401 "Unauthorized access - the user is not authenticated or does not have the necessary permissions. Ensure that you have provided a valid API key or JWT token, and that you have the required permissions."
|
||||
|
@ -36,6 +37,12 @@ func (handler *Handler) getKubernetesNamespaces(w http.ResponseWriter, r *http.R
|
|||
return httperror.BadRequest("an error occurred during the GetKubernetesNamespaces operation, invalid query parameter withResourceQuota. Error: ", err)
|
||||
}
|
||||
|
||||
withUnhealthyEvents, err := request.RetrieveBooleanQueryParameter(r, "withUnhealthyEvents", true)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("context", "GetKubernetesNamespaces").Msg("Invalid query parameter withUnhealthyEvents")
|
||||
return httperror.BadRequest("an error occurred during the GetKubernetesNamespaces operation, invalid query parameter withUnhealthyEvents. Error: ", err)
|
||||
}
|
||||
|
||||
cli, httpErr := handler.prepareKubeClient(r)
|
||||
if httpErr != nil {
|
||||
log.Error().Err(httpErr).Str("context", "GetKubernetesNamespaces").Msg("Unable to get a Kubernetes client for the user")
|
||||
|
@ -48,6 +55,14 @@ func (handler *Handler) getKubernetesNamespaces(w http.ResponseWriter, r *http.R
|
|||
return httperror.InternalServerError("an error occurred during the GetKubernetesNamespaces operation, unable to retrieve namespaces from the Kubernetes cluster. Error: ", err)
|
||||
}
|
||||
|
||||
if withUnhealthyEvents {
|
||||
namespaces, err = cli.CombineNamespacesWithUnhealthyEvents(namespaces)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("context", "GetKubernetesNamespaces").Msg("Unable to combine namespaces with unhealthy events")
|
||||
return httperror.InternalServerError("an error occurred during the GetKubernetesNamespaces operation, unable to combine namespaces with unhealthy events. Error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
if withResourceQuota {
|
||||
return cli.CombineNamespacesWithResourceQuotas(namespaces, w)
|
||||
}
|
||||
|
|
|
@ -351,6 +351,34 @@ func (kcl *KubeClient) DeleteNamespace(namespaceName string) (*corev1.Namespace,
|
|||
return namespace, nil
|
||||
}
|
||||
|
||||
// CombineNamespacesWithUnhealthyEvents combines namespaces with unhealthy events across all namespaces
|
||||
func (kcl *KubeClient) CombineNamespacesWithUnhealthyEvents(namespaces map[string]portainer.K8sNamespaceInfo) (map[string]portainer.K8sNamespaceInfo, error) {
|
||||
allEvents, err := kcl.GetEvents("", "")
|
||||
if err != nil && !k8serrors.IsNotFound(err) {
|
||||
log.Error().
|
||||
Str("context", "CombineNamespacesWithUnhealthyEvents").
|
||||
Err(err).
|
||||
Msg("unable to retrieve unhealthy events from the Kubernetes for an admin user")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unhealthyEventCounts := make(map[string]int)
|
||||
for _, event := range allEvents {
|
||||
if event.Type == "Warning" {
|
||||
unhealthyEventCounts[event.Namespace]++
|
||||
}
|
||||
}
|
||||
|
||||
for namespaceName, namespace := range namespaces {
|
||||
if count, exists := unhealthyEventCounts[namespaceName]; exists {
|
||||
namespace.UnhealthyEventCount = count
|
||||
namespaces[namespaceName] = namespace
|
||||
}
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
// CombineNamespacesWithResourceQuotas combines namespaces with resource quotas where matching is based on "portainer-rq-"+namespace.Name
|
||||
func (kcl *KubeClient) CombineNamespacesWithResourceQuotas(namespaces map[string]portainer.K8sNamespaceInfo, w http.ResponseWriter) *httperror.HandlerError {
|
||||
resourceQuotas, err := kcl.GetResourceQuotas("")
|
||||
|
|
|
@ -621,15 +621,16 @@ type (
|
|||
JobType int
|
||||
|
||||
K8sNamespaceInfo struct {
|
||||
Id string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
Status corev1.NamespaceStatus `json:"Status"`
|
||||
Annotations map[string]string `json:"Annotations"`
|
||||
CreationDate string `json:"CreationDate"`
|
||||
NamespaceOwner string `json:"NamespaceOwner"`
|
||||
IsSystem bool `json:"IsSystem"`
|
||||
IsDefault bool `json:"IsDefault"`
|
||||
ResourceQuota *corev1.ResourceQuota `json:"ResourceQuota"`
|
||||
Id string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
Status corev1.NamespaceStatus `json:"Status"`
|
||||
Annotations map[string]string `json:"Annotations"`
|
||||
CreationDate string `json:"CreationDate"`
|
||||
UnhealthyEventCount int `json:"UnhealthyEventCount"`
|
||||
NamespaceOwner string `json:"NamespaceOwner"`
|
||||
IsSystem bool `json:"IsSystem"`
|
||||
IsDefault bool `json:"IsDefault"`
|
||||
ResourceQuota *corev1.ResourceQuota `json:"ResourceQuota"`
|
||||
}
|
||||
|
||||
K8sNodeLimits struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue