Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): Requests info for Cpu and Mem added to Pod details #20637

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions controller/cache/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ func populatePodInfo(un *unstructured.Unstructured, res *ResourceInfo) {
}

req, _ := resourcehelper.PodRequestsAndLimits(&pod)
CPUReq, MemoryReq := req[v1.ResourceCPU], req[v1.ResourceMemory]

res.PodInfo = &PodInfo{NodeName: pod.Spec.NodeName, ResourceRequests: req, Phase: pod.Status.Phase}

res.Info = append(res.Info, v1alpha1.InfoItem{Name: "Node", Value: pod.Spec.NodeName})
Expand All @@ -454,6 +456,13 @@ func populatePodInfo(un *unstructured.Unstructured, res *ResourceInfo) {
res.Info = append(res.Info, v1alpha1.InfoItem{Name: "Restart Count", Value: fmt.Sprintf("%d", restarts)})
}

// requests will be released for terminated pods either with success or failed state termination.

if reason != "Completed" && reason != "Error" {
res.Info = append(res.Info, v1alpha1.InfoItem{Name: "Requests (CPU)", Value: fmt.Sprintf("%d", CPUReq.MilliValue())})
res.Info = append(res.Info, v1alpha1.InfoItem{Name: "Requests (MEM)", Value: fmt.Sprintf("%d", MemoryReq.MilliValue())})
}

var urls []string
if res.NetworkingInfo != nil {
urls = res.NetworkingInfo.ExternalURLs
Expand Down
171 changes: 171 additions & 0 deletions controller/cache/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ func TestGetPodInfo(t *testing.T) {
assert.Equal(t, []v1alpha1.InfoItem{
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "134217728000"},
}, info.Info)
assert.Equal(t, []string{"bar"}, info.Images)
assert.Equal(t, &PodInfo{
Expand Down Expand Up @@ -367,9 +369,81 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "Running"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "1/1"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

t.Run("TestGetPodWithInitialContainerInfoWithResources", func(t *testing.T) {
pod := strToUnstructured(`
apiVersion: "v1"
kind: "Pod"
metadata:
labels:
app: "app-with-initial-container"
name: "app-with-initial-container-5f46976fdb-vd6rv"
namespace: "default"
ownerReferences:
- apiVersion: "apps/v1"
kind: "ReplicaSet"
name: "app-with-initial-container-5f46976fdb"
spec:
containers:
- image: "alpine:latest"
imagePullPolicy: "Always"
name: "app-with-initial-container"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
initContainers:
- image: "alpine:latest"
imagePullPolicy: "Always"
name: "app-with-initial-container-logshipper"
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "256Mi"
nodeName: "minikube"
status:
containerStatuses:
- image: "alpine:latest"
name: "app-with-initial-container"
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2024-10-08T08:44:25Z"
initContainerStatuses:
- image: "alpine:latest"
name: "app-with-initial-container-logshipper"
ready: true
restartCount: 0
started: false
state:
terminated:
exitCode: 0
reason: "Completed"
phase: "Running"
`)

info := &ResourceInfo{}
populateNodeInfo(pod, info, []string{})
assert.Equal(t, []v1alpha1.InfoItem{
{Name: "Status Reason", Value: "Running"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "1/1"},
{Name: "Requests (CPU)", Value: "100"},
{Name: "Requests (MEM)", Value: "134217728000"},
}, info.Info)
})
t.Run("TestGetPodInfoWithSidecar", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -424,6 +498,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "Running"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "2/2"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -482,6 +558,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "Init:0/1"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -539,6 +617,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/3"},
{Name: "Restart Count", Value: "3"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -596,6 +676,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/3"},
{Name: "Restart Count", Value: "3"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -656,6 +738,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "1/3"},
{Name: "Restart Count", Value: "7"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -698,6 +782,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
{Name: "Restart Count", Value: "3"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -733,6 +819,45 @@ func TestGetPodInfo(t *testing.T) {
}, info.Info)
})

// Test pod condition succeed which had some allocated resources
t.Run("TestPodConditionSucceededWithResources", func(t *testing.T) {
t.Parallel()

pod := strToUnstructured(`
apiVersion: v1
kind: Pod
metadata:
name: test8
spec:
nodeName: minikube
containers:
- name: container
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "256Mi"
status:
phase: Succeeded
containerStatuses:
- ready: false
restartCount: 0
state:
terminated:
reason: Completed
exitCode: 0
`)
info := &ResourceInfo{}
populateNodeInfo(pod, info, []string{})
assert.Equal(t, []v1alpha1.InfoItem{
{Name: "Status Reason", Value: "Completed"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
}, info.Info)
})

// Test pod condition failed
t.Run("TestPodConditionFailed", func(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -765,6 +890,46 @@ func TestGetPodInfo(t *testing.T) {
}, info.Info)
})

// Test pod condition failed with allocated resources

t.Run("TestPodConditionFailedWithResources", func(t *testing.T) {
t.Parallel()

pod := strToUnstructured(`
apiVersion: v1
kind: Pod
metadata:
name: test9
spec:
nodeName: minikube
containers:
- name: container
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "256Mi"
status:
phase: Failed
containerStatuses:
- ready: false
restartCount: 0
state:
terminated:
reason: Error
exitCode: 1
`)
info := &ResourceInfo{}
populateNodeInfo(pod, info, []string{})
assert.Equal(t, []v1alpha1.InfoItem{
{Name: "Status Reason", Value: "Error"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
}, info.Info)
})

// Test pod condition succeed with deletion
t.Run("TestPodConditionSucceededWithDeletion", func(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -826,6 +991,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "Terminating"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand All @@ -852,6 +1019,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "Terminating"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})

Expand Down Expand Up @@ -882,6 +1051,8 @@ func TestGetPodInfo(t *testing.T) {
{Name: "Status Reason", Value: "SchedulingGated"},
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/2"},
{Name: "Requests (CPU)", Value: "0"},
{Name: "Requests (MEM)", Value: "0"},
}, info.Info)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import Moment from 'react-moment';
import {Pod} from '../../../shared/models';
import {isYoungerThanXMinutes} from '../utils';
import {formatSize} from './pod-view';

export const PodTooltip = (props: {pod: Pod}) => {
const pod = props.pod;
Expand All @@ -16,15 +17,22 @@ export const PodTooltip = (props: {pod: Pod}) => {
<div className='columns small-6'>{pod.health}</div>
</div>
{(pod.info || [])
.filter(i => i.name !== 'Node')
.map(i => (
<div className='row' key={i.name}>
<div className='columns small-6' style={{whiteSpace: 'nowrap'}}>
{i.name}:
.filter(i => {
//filter out 0 values for CPU and mem on pod info
return i.name !== 'Node' && !((i.name === 'Requests (CPU)' || i.name === 'Requests (MEM)') && parseInt(i.value, 10) === 0);
})
.map(i => {
//formatted the values here for info for cpu and mem
const formattedValue = formatPodMetric(i.name, i.value);
return (
<div className='row' key={i.name}>
<div className='columns small-6' style={{whiteSpace: 'nowrap'}}>
{i.name}:
</div>
<div className='columns small-6'>{formattedValue}</div>
</div>
<div className='columns small-6'>{i.value}</div>
</div>
))}
);
})}
{pod.createdAt && (
<div className='row'>
<div className='columns small-6'>
Expand All @@ -49,3 +57,17 @@ export const PodTooltip = (props: {pod: Pod}) => {
</div>
);
};

function formatPodMetric(name: string, value: string) {
const numericValue = parseInt(value, 10);

switch (name) {
case 'Requests (CPU)':
return `${numericValue}m`;
case 'Requests (MEM)': {
return formatSize(numericValue / 1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be / 1024?

}
default:
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ $pod-age-icon-clr: #ffce25;
}
}
&__info {
margin-top: 1em;
margin-top: 3em;
display: flex;
justify-content: end;
div {
Expand All @@ -69,6 +69,22 @@ $pod-age-icon-clr: #ffce25;
margin-right: 5px;
padding: 3px 5px;
}
#cost {
background-color: $argo-color-gray-7;
color: whitesmoke;
padding: 5px 8px;
font-weight: bold;
margin-right: auto;
transition: background-color 0.3s ease, box-shadow 0.3s ease, transform 0.2s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border: 1px solid lighten($argo-color-gray-7, 10%);


&:hover {
background-color: darken($argo-color-gray-7, 10%);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}
}
}
&__info--large {
margin: 1em 0;
Expand Down
Loading