1.0 - has search, pulse
Build and Publish Docker Image / Build and Push Docker Image (push) Successful in 1m24s
Details
Build and Publish Docker Image / Build and Push Docker Image (push) Successful in 1m24s
Details
This commit is contained in:
parent
7f3fcd4b50
commit
6d2a5f1a8a
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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 }}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
version = 0.9
|
version = 1.0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue