1.0 - has search, pulse
Build and Publish Docker Image / Build and Push Docker Image (push) Successful in 1m24s Details

This commit is contained in:
Isaac Johnson 2026-08-01 20:43:09 -05:00
parent 7f3fcd4b50
commit 6d2a5f1a8a
7 changed files with 96 additions and 15 deletions

View File

@ -2,5 +2,5 @@ apiVersion: v2
name: k8s-pulse name: k8s-pulse
description: A Helm chart for k8s-pulse, a Kubernetes cluster resource visualizer. description: A Helm chart for k8s-pulse, a Kubernetes cluster resource visualizer.
type: application type: application
version: 0.1.1 version: 0.1.2
appVersion: "1.0.8" appVersion: "1.1.0"

View File

@ -44,14 +44,18 @@ spec:
httpGet: httpGet:
path: /healthz path: /healthz
port: http port: http
initialDelaySeconds: 10 initialDelaySeconds: 15
periodSeconds: 10 periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 5
readinessProbe: readinessProbe:
httpGet: httpGet:
path: /healthz path: /healthz
port: http port: http
initialDelaySeconds: 5 initialDelaySeconds: 10
periodSeconds: 10 periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 5
resources: resources:
{{- toYaml .Values.resources | nindent 12 }} {{- toYaml .Values.resources | nindent 12 }}
{{- if or .Values.persistence.enabled .Values.kubeconfig.enabled }} {{- if or .Values.persistence.enabled .Values.kubeconfig.enabled }}

View File

@ -65,11 +65,11 @@ ingress:
resources: resources:
limits: limits:
cpu: 200m cpu: 500m
memory: 256Mi memory: 512Mi
requests: requests:
cpu: 100m cpu: 250m
memory: 128Mi memory: 256Mi
persistence: persistence:
enabled: false enabled: false

View File

@ -151,6 +151,8 @@ let hoveredPod = null;
let maxCpuInCluster = 1; let maxCpuInCluster = 1;
let maxMemInCluster = 1; let maxMemInCluster = 1;
let autoRotateEnabled = false; let autoRotateEnabled = false;
let currentSearchTerm = '';
const searchHighlightColor = new THREE.Color(0xffffff);
// Formatters // Formatters
const formatBytes = (bytes) => { const formatBytes = (bytes) => {
@ -199,6 +201,39 @@ document.getElementById('btn-auto-rotate').addEventListener('click', () => {
} }
}); });
document.getElementById('pod-search').addEventListener('input', (e) => {
currentSearchTerm = e.target.value.toLowerCase().trim();
podMeshes.forEach(mesh => {
if (mesh !== hoveredPod) {
applySearchStyle(mesh);
}
});
});
function applySearchStyle(mesh) {
mesh.isSearchHighlighted = false;
if (mesh.userData.type === 'unused') {
mesh.material.emissive.setHex(mesh.originalEmissive);
mesh.material.emissiveIntensity = mesh.originalEmissiveIntensity;
return;
}
if (!currentSearchTerm) {
mesh.material.emissive.setHex(mesh.originalEmissive);
mesh.material.emissiveIntensity = mesh.originalEmissiveIntensity;
return;
}
const podName = (mesh.userData.name || '').toLowerCase();
if (podName.includes(currentSearchTerm)) {
mesh.isSearchHighlighted = true;
} else {
mesh.material.emissive.setHex(mesh.originalEmissive);
mesh.material.emissiveIntensity = 0.05;
}
}
document.getElementById('theme-select').addEventListener('change', (e) => { document.getElementById('theme-select').addEventListener('change', (e) => {
const theme = e.target.value; const theme = e.target.value;
currentTheme = theme; currentTheme = theme;
@ -603,8 +638,11 @@ function build3DCluster(data) {
podMesh.baseCenterZ = centerZ; podMesh.baseCenterZ = centerZ;
podMesh.originalColor = color; podMesh.originalColor = color;
podMesh.originalEmissive = emissive; podMesh.originalEmissive = emissive;
podMesh.originalEmissiveColor = new THREE.Color(emissive);
podMesh.originalEmissiveIntensity = p.data.type === 'unused' ? 0.05 : 0.25; podMesh.originalEmissiveIntensity = p.data.type === 'unused' ? 0.05 : 0.25;
applySearchStyle(podMesh);
scene.add(podMesh); scene.add(podMesh);
podMeshes.push(podMesh); podMeshes.push(podMesh);
}); });
@ -637,6 +675,9 @@ function updatePodHeights() {
function animate() { function animate() {
requestAnimationFrame(animate); requestAnimationFrame(animate);
const time = performance.now();
const pulseFactor = (Math.sin(time * 0.005) + 1) / 2;
// Smoothly interpolate pod tower heights (lerp) // Smoothly interpolate pod tower heights (lerp)
podMeshes.forEach(mesh => { podMeshes.forEach(mesh => {
if (Math.abs(mesh.currentHeight - mesh.targetHeight) > 0.01) { if (Math.abs(mesh.currentHeight - mesh.targetHeight) > 0.01) {
@ -645,6 +686,13 @@ function animate() {
// Keep tower base resting on the node platform at y = 1.5 // Keep tower base resting on the node platform at y = 1.5
mesh.position.y = 1.5 + mesh.currentHeight / 2; mesh.position.y = 1.5 + mesh.currentHeight / 2;
} }
if (mesh.isSearchHighlighted && mesh !== hoveredPod) {
if (mesh.originalEmissiveColor) {
mesh.material.emissive.copy(mesh.originalEmissiveColor).lerp(searchHighlightColor, pulseFactor);
}
mesh.material.emissiveIntensity = mesh.originalEmissiveIntensity + (0.8 - mesh.originalEmissiveIntensity) * pulseFactor;
}
}); });
controls.update(); controls.update();
@ -674,8 +722,7 @@ function onPointerMove(event) {
if (hoveredPod !== hitMesh) { if (hoveredPod !== hitMesh) {
// Reset previous hovered pod // Reset previous hovered pod
if (hoveredPod && hoveredPod.userData && hoveredPod.userData.type !== 'node' && hoveredPod.material && hoveredPod.material.emissive) { if (hoveredPod && hoveredPod.userData && hoveredPod.userData.type !== 'node' && hoveredPod.material && hoveredPod.material.emissive) {
hoveredPod.material.emissive.setHex(hoveredPod.originalEmissive); applySearchStyle(hoveredPod);
hoveredPod.material.emissiveIntensity = hoveredPod.originalEmissiveIntensity;
} }
hoveredPod = hitMesh; hoveredPod = hitMesh;
@ -781,8 +828,7 @@ function onPointerMove(event) {
container.style.cursor = 'grab'; container.style.cursor = 'grab';
if (hoveredPod) { if (hoveredPod) {
if (hoveredPod.userData && hoveredPod.userData.type !== 'node' && hoveredPod.material && hoveredPod.material.emissive) { if (hoveredPod.userData && hoveredPod.userData.type !== 'node' && hoveredPod.material && hoveredPod.material.emissive) {
hoveredPod.material.emissive.setHex(hoveredPod.originalEmissive); applySearchStyle(hoveredPod);
hoveredPod.material.emissiveIntensity = hoveredPod.originalEmissiveIntensity;
} }
hoveredPod = null; hoveredPod = null;
} }

View File

@ -185,6 +185,34 @@ body {
gap: 1rem; gap: 1rem;
} }
.search-container {
display: flex;
align-items: center;
}
.search-input {
background: rgba(15, 23, 42, 0.6);
color: var(--text-main);
border: 1px solid var(--glass-border);
padding: 0.5rem 1rem;
font-size: 0.875rem;
font-weight: 500;
border-radius: 0.5rem;
outline: none;
transition: all 0.2s ease;
width: 220px;
}
.search-input:focus {
background: rgba(30, 41, 59, 0.9);
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}
.search-input::placeholder {
color: var(--text-muted);
}
.toggle-container { .toggle-container {
display: flex; display: flex;
background: rgba(15, 23, 42, 0.6); background: rgba(15, 23, 42, 0.6);

View File

@ -22,6 +22,9 @@
<h1>K8s Pulse <span class="badge-3d">3D</span></h1> <h1>K8s Pulse <span class="badge-3d">3D</span></h1>
</div> </div>
<div class="controls"> <div class="controls">
<div class="search-container">
<input type="text" id="pod-search" class="search-input glass-panel" placeholder="Search Pods..." autocomplete="off">
</div>
<div class="toggle-container"> <div class="toggle-container">
<button class="toggle-btn active" id="btn-cpu">CPU Consumption</button> <button class="toggle-btn active" id="btn-cpu">CPU Consumption</button>
<button class="toggle-btn" id="btn-mem">Memory Consumption</button> <button class="toggle-btn" id="btn-mem">Memory Consumption</button>

View File

@ -1,2 +1,2 @@
[metadata] [metadata]
version = 0.9 version = 1.0