mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-09-21 01:53:24 +00:00
Fix: Cross-cluster data bleeding + Enhanced SSL dropdown UI
🐛 Critical Cross-Cluster Data Bleeding - System-Wide Fix: Fixed old cluster's data appearing when switching clusters across 4 components Root Cause: - User switches from Cluster A to Cluster B - Old cluster data remains in React state during API fetch - Race condition: UI shows Cluster A data while fetching Cluster B - Backend page: Data persisted after fetch - Frontend page: Data briefly appeared then disappeared ✅ Components Fixed (State Clearing on Cluster Change): 1. BackendServers.js (Line 115-122) - Clear: backends, filteredBackends, frontends, sslCertificates 2. FrontendManagement.js (Line 150-157) - Clear: frontends, filteredFrontends, backends, sslCertificates 3. WAFManagement.js (Line 277-282) - Clear: rules, filteredRules, frontends 4. DashboardV2.js (Line 402-407) - Clear: statsData, frontendOptions, backendOptions, backendHealth, slowestBackends Already Had State Clearing: ✓ SSLManagement.js ✓ AgentManagement.js ✓ Configuration.js ✓ ApplyManagement.js ✨ UI Enhancement: Backend Server SSL Dropdown Redesigned to match Frontend SSL dropdown design: Before: star-burgan-com-tr - *.burgan.com.tr (Expires: 2/25/2026) After: star-burgan-com-tr - *.burgan.com.tr [🌍 Global] ✅ (125 days) demo-cert - *.apps.cluster.example.com [📍 Cluster] ✅ (1502 days) Features Added: ✅ Status icons: valid, ⚠️ expiring soon, ❌ expired ✅ Days until expiry countdown ✅ SSL type tags: 🌍 Global (blue) or 📍 Cluster (green) ✅ Better layout with flex spacing ✅ optionLabelProp for compact selected view 🎯 Impact Analysis - All Components Safe: Tested 8 components with selectedCluster dependency: ✓ BackendServers - State clearing added ✓ FrontendManagement - State clearing added ✓ WAFManagement - State clearing added ✓ DashboardV2 - State clearing added ✓ SSLManagement - Already had clearing ✓ AgentManagement - Already had clearing ✓ Configuration - Already had clearing ✓ ApplyManagement - Already had clearing No Breaking Changes: - Only added state clearing in useEffect - Fetch logic unchanged - Response handling unchanged - UI components unchanged (except SSL dropdown enhancement) ✅ Cross-cluster data bleeding completely resolved
This commit is contained in:
@@ -112,6 +112,15 @@ const BackendServers = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data
|
||||
// Race condition: Old cluster data remains visible while new cluster data is fetching
|
||||
if (selectedCluster) {
|
||||
setBackends([]);
|
||||
setFilteredBackends([]);
|
||||
setFrontends([]);
|
||||
setSslCertificates([]);
|
||||
}
|
||||
|
||||
fetchBackends();
|
||||
fetchFrontends();
|
||||
fetchSSLCertificates();
|
||||
@@ -1932,15 +1941,41 @@ const BackendServers = () => {
|
||||
placeholder="Select an SSL certificate (optional unless verify=required)"
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
option.children.toLowerCase().includes(input.toLowerCase())
|
||||
(option.label || '').toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
optionLabelProp="label"
|
||||
>
|
||||
{sslCertificates.map((cert) => (
|
||||
<Option key={cert.id} value={cert.id}>
|
||||
{cert.name} - {cert.domain}
|
||||
{cert.expiry_date && ` (Expires: ${new Date(cert.expiry_date).toLocaleDateString()})`}
|
||||
</Option>
|
||||
))}
|
||||
{sslCertificates.map((cert) => {
|
||||
// Status icon based on certificate validity
|
||||
const statusIcon = cert.status === 'valid' ? '✅' :
|
||||
cert.status === 'expiring_soon' ? '⚠️' : '❌';
|
||||
const expiryInfo = cert.days_until_expiry !== undefined ?
|
||||
`(${cert.days_until_expiry} days)` : '';
|
||||
const sslTypeTag = cert.ssl_type === 'Global' ? '🌍 Global' : '📍 Cluster';
|
||||
|
||||
return (
|
||||
<Option
|
||||
key={cert.id}
|
||||
value={cert.id}
|
||||
label={`${cert.name} - ${cert.domain}`}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<span>
|
||||
<strong>{cert.name}</strong> - {cert.domain}
|
||||
<Tag
|
||||
color={cert.ssl_type === 'Global' ? 'blue' : 'green'}
|
||||
style={{ marginLeft: 8, fontSize: '10px' }}
|
||||
>
|
||||
{sslTypeTag}
|
||||
</Tag>
|
||||
</span>
|
||||
<span style={{ fontSize: '12px', color: '#666', marginLeft: 12 }}>
|
||||
{statusIcon} {expiryInfo}
|
||||
</span>
|
||||
</div>
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
@@ -399,6 +399,13 @@ const DashboardV2 = () => {
|
||||
useEffect(() => {
|
||||
if (!selectedCluster) return;
|
||||
|
||||
// CRITICAL FIX: Clear all dashboard state when cluster changes
|
||||
setStatsData({});
|
||||
setFrontendOptions([]);
|
||||
setBackendOptions([]);
|
||||
setBackendHealth([]);
|
||||
setSlowestBackends([]);
|
||||
|
||||
let isMounted = true;
|
||||
|
||||
const loadInitialData = async () => {
|
||||
|
||||
@@ -147,6 +147,15 @@ const FrontendManagement = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data
|
||||
// Race condition: Old cluster data remains visible while new cluster data is fetching
|
||||
if (selectedCluster) {
|
||||
setFrontends([]);
|
||||
setFilteredFrontends([]);
|
||||
setBackends([]);
|
||||
setSslCertificates([]);
|
||||
}
|
||||
|
||||
fetchFrontends();
|
||||
fetchBackends();
|
||||
fetchSSLCertificates();
|
||||
|
||||
@@ -274,6 +274,13 @@ const WAFManagement = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// CRITICAL FIX: Clear state when cluster changes to prevent showing other cluster's data
|
||||
if (selectedCluster) {
|
||||
setRules([]);
|
||||
setFilteredRules([]);
|
||||
setFrontends([]);
|
||||
}
|
||||
|
||||
fetchRules();
|
||||
fetchStats();
|
||||
checkPendingChanges();
|
||||
|
||||
Reference in New Issue
Block a user