diff --git a/cyclops-ctrl/internal/models/dto/k8s.go b/cyclops-ctrl/internal/models/dto/k8s.go index 04c1404e..91bc93cf 100644 --- a/cyclops-ctrl/internal/models/dto/k8s.go +++ b/cyclops-ctrl/internal/models/dto/k8s.go @@ -19,15 +19,16 @@ type Resource interface { } type Deployment struct { - Group string `json:"group"` - Version string `json:"version"` - Kind string `json:"kind"` - Name string `json:"name"` - Namespace string `json:"namespace"` - Replicas int `json:"replicas"` - Pods []Pod `json:"pods"` - Status string `json:"status"` - Deleted bool `json:"deleted"` + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + Name string `json:"name"` + Namespace string `json:"namespace"` + Replicas int `json:"replicas"` + Pods []Pod `json:"pods"` + Status string `json:"status"` + Deleted bool `json:"deleted"` + ActiveReplicaSet string `json:"activeReplicaSet"` } func (d *Deployment) GetGroupVersionKind() string { @@ -222,6 +223,7 @@ type Pod struct { Status bool `json:"status"` Started *metav1.Time `json:"started"` Deleted bool `json:"deleted"` + ReplicaSet string `json:"replicaSet"` } func (p *Pod) GetGroupVersionKind() string { diff --git a/cyclops-ctrl/pkg/cluster/k8sclient/mapper.go b/cyclops-ctrl/pkg/cluster/k8sclient/mapper.go index be20af93..5455b7ed 100644 --- a/cyclops-ctrl/pkg/cluster/k8sclient/mapper.go +++ b/cyclops-ctrl/pkg/cluster/k8sclient/mapper.go @@ -2,6 +2,9 @@ package k8sclient import ( "context" + "strings" + + appsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -22,14 +25,15 @@ func (k *KubernetesClient) mapDeployment(group, version, kind, name, namespace s } return &dto.Deployment{ - Group: group, - Version: version, - Kind: kind, - Name: deployment.Name, - Namespace: deployment.Namespace, - Replicas: int(*deployment.Spec.Replicas), - Pods: pods, - Status: getDeploymentStatus(deployment), + Group: group, + Version: version, + Kind: kind, + Name: deployment.Name, + Namespace: deployment.Namespace, + Replicas: int(*deployment.Spec.Replicas), + Pods: pods, + Status: getDeploymentStatus(deployment), + ActiveReplicaSet: getActiveReplicaSet(deployment.Status.Conditions), }, nil } @@ -455,3 +459,26 @@ func mapIPBlock(block *networkingv1.IPBlock) *dto.IPBlock { Except: block.Except, } } + +func getActiveReplicaSet(conditions []appsv1.DeploymentCondition) string { + var latestProgressingCondition *appsv1.DeploymentCondition + + for _, condition := range conditions { + if condition.Type == appsv1.DeploymentProgressing { + if latestProgressingCondition == nil || condition.LastTransitionTime.After(latestProgressingCondition.LastTransitionTime.Time) { + latestProgressingCondition = &condition + } + } + } + + if latestProgressingCondition != nil { + if strings.Contains(latestProgressingCondition.Message, "ReplicaSet") { + parts := strings.Split(latestProgressingCondition.Message, "\"") + if len(parts) > 1 { + return parts[1] // ReplicaSet \".+\" is progressing. status: Progressing + } + } + } + + return "" +} diff --git a/cyclops-ctrl/pkg/cluster/k8sclient/modules.go b/cyclops-ctrl/pkg/cluster/k8sclient/modules.go index fd3c4d33..5acb7877 100644 --- a/cyclops-ctrl/pkg/cluster/k8sclient/modules.go +++ b/cyclops-ctrl/pkg/cluster/k8sclient/modules.go @@ -537,6 +537,7 @@ func (k *KubernetesClient) getPods(deployment appsv1.Deployment) ([]dto.Pod, err Node: item.Spec.NodeName, PodPhase: string(item.Status.Phase), Started: item.Status.StartTime, + ReplicaSet: getReplicaSetOwner(&item), }) } @@ -841,6 +842,16 @@ func containerStatus(status apiv1.ContainerStatus) dto.ContainerStatus { } } +func getReplicaSetOwner(pod *apiv1.Pod) string { + for _, reference := range pod.OwnerReferences { + if reference.Kind == "ReplicaSet" { + return reference.Name + } + } + + return "" +} + func getDeploymentStatus(deployment *appsv1.Deployment) string { if isDeploymentProgressing(deployment.Status.Conditions) { return statusProgressing diff --git a/cyclops-ui/src/components/k8s-resources/Deployment.tsx b/cyclops-ui/src/components/k8s-resources/Deployment.tsx index e94cc92e..39cd25b8 100644 --- a/cyclops-ui/src/components/k8s-resources/Deployment.tsx +++ b/cyclops-ui/src/components/k8s-resources/Deployment.tsx @@ -1,9 +1,10 @@ -import React, { useCallback, useEffect, useState } from "react"; -import { Col, Divider, Row, Alert } from "antd"; +import { Alert, Col, Divider, Row } from "antd"; import axios from "axios"; +import { useCallback, useEffect, useState } from "react"; +import { isStreamingEnabled } from "../../utils/api/common"; import { mapResponseError } from "../../utils/api/errors"; import PodTable from "./common/PodTable/PodTable"; -import { isStreamingEnabled } from "../../utils/api/common"; +import ReplicaSetProgress from "./common/ReplicaSetProgress"; interface Props { name: string; @@ -15,6 +16,8 @@ const Deployment = ({ name, namespace, workload }: Props) => { const [deployment, setDeployment] = useState({ status: "", pods: [], + replicas: 0, + activeReplicaSet: "", }); const [error, setError] = useState({ message: "", @@ -43,10 +46,6 @@ const Deployment = ({ name, namespace, workload }: Props) => { useEffect(() => { fetchDeployment(); - if (isStreamingEnabled()) { - return; - } - const interval = setInterval(() => fetchDeployment(), 15000); return () => { clearInterval(interval); @@ -71,6 +70,8 @@ const Deployment = ({ name, namespace, workload }: Props) => { return 0; } + const { pods, replicas, activeReplicaSet } = deployment; + return (