Code cleanup - removed emoji from form field
Changed: extra="🆕 Select one or more..."
To: extra="Select one or more..."
Note: Backend Server SSL is single select (correct)
Frontend SSL is multiple select (correct - supports SNI)
CRITICAL RACE CONDITION FIX - FrontendManagement:
Same race condition pattern found and fixed
Component Analysis:
BackendServers: FIXED (guard clause added)
FrontendManagement: FIXED (guard clause added)
SSLManagement: Already has guard clause
WAFManagement: Already has guard clause
FrontendManagement Issues Fixed:
1. fetchFrontends() - Added guard clause
if (!selectedCluster) → Clear state and return
2. fetchBackends() - Added guard clause
if (!selectedCluster) → Clear state and return
Race Condition Pattern:
Mount → selectedCluster=undefined → fetch() → API returns ALL
Load → selectedCluster=1 → fetch() → API returns filtered
Problem: First response arrives late and overwrites correct data
Solution - Guard Clauses:
if (!selectedCluster) {
setEntities([]);
setFilteredEntities([]);
return; // Don't call API
}
Risk Assessment - SAFE:
- Only adds early return if no cluster selected
- Doesn't change existing logic when cluster IS selected
- Same pattern already used in SSLManagement and WAFManagement
- No breaking changes to other functions
Impact:
- Prevents race condition on component mount
- Prevents all entities appearing briefly
- Consistent behavior across all management pages
Tested Components:
Backend/Frontend/SSL/WAF Management all now protected
Added debug logging to fetchBackends:
- Log selectedCluster info
- Log params object being sent to API
- Log API response data (total count, IDs, cluster_ids)
This will help identify why wrong cluster backends are appearing:
- If params shows cluster_id: undefined → selectedCluster issue
- If params correct but response wrong → backend API issue
- If response correct but UI wrong → state/filter issue
Logs will appear in browser console with prefix:
FETCH BACKENDS DEBUG
FETCH BACKENDS RESPONSE
After testing, these logs can be removed or converted to conditional debug mode
Database Migration:
- Added ssl_certificate_id column to backend_servers table
- Added FK constraint to ssl_certificates table
- ON DELETE SET NULL behavior
- Idempotent migration (safe to run multiple times)
Column Details:
Name: ssl_certificate_id
Type: INTEGER
Nullable: YES
Foreign Key: ssl_certificates(id)
On Delete: SET NULL
Migration Function:
add_ssl_certificate_id_to_backend_servers()
Called in run_migrations() at Line 1523
Code Cleanup:
- Removed emojis from migration logs
- Removed emojis from SSL dropdown status icons
- Changed to text: Valid, Expiring, Expired
- Changed to text: Global, Cluster
Error Fixed:
GET /api/backends - 500
column "ssl_certificate_id" does not exist
After migration runs on startup, column will exist and API will work
🐛 Bug Fix:
- Fixed SSL certificate dropdown showing empty list in Backend Server edit
- Backend Server SSL dropdown now loads certificates correctly
🔧 Technical Details:
- Wrong API endpoint: /api/ssl-certificates (incorrect)
- Correct endpoint: /api/ssl/certificates (same as Frontend)
- Added cluster_id filtering and Authorization header
- Added debug logging for troubleshooting
✅ Now Shows (Verified with Query Analysis):
- Global SSL certificates (available to all clusters)
- Cluster-specific SSL certificates for SELECTED cluster only
- Other clusters' specific SSLs are NOT shown (correct behavior)
💡 SSL Enable Logic (HAProxy Standard):
Current implementation is CORRECT per HAProxy syntax:
server name addr:port ssl [verify required]
The 'ssl' flag MUST be present before 'verify' can be used.
Therefore: SSL Enable switch → SSL dropdown (correct behavior)
Example HAProxy syntax:
✅ server es1 10.0.0.1:443 ssl verify required ca-file /path/cert.pem
❌ server es1 10.0.0.1:443 verify required (invalid - missing ssl flag)
Query Logic (Line 173-176 backend/routers/ssl.py):
Global: NOT EXISTS in ssl_certificate_clusters
Cluster-specific: scc.cluster_id = selected_cluster_id
🐛 Critical Bug Fix:
- Fixed 'list' object has no attribute 'strip' error
- Error occurred in _validate_parsed_config() at line 847
- use_backend_rules is now a list, not a string
🔧 Technical Details:
- Changed from: frontend.use_backend_rules.strip()
- Changed to: bool(frontend.use_backend_rules)
- Simple boolean check works for both list and None types
✅ Impact:
- Bulk import parsing now works without errors
- Config validation properly handles list-based use_backend_rules
- All warning messages display correctly
Error was:
'list' object has no attribute 'strip'
at _validate_parsed_config line 847
Fix applied:
Line 847-848: Use bool() instead of .strip() for list validation
✨ New Features:
- Added use_backend_rules validator to Frontend model
- UI now supports editing use_backend rules from Frontend Management page
- Array to string conversion for use_backend rules in edit modal
🔧 Model Improvements:
- Changed use_backend_rules field type from Optional[str] to Any (list support)
- Added parse_use_backend_rules validator (same logic as ACL/redirect rules)
- Handles 3 formats: Array, Textarea string (newline-separated), JSON string
💡 UI Improvements:
- Frontend edit modal automatically converts use_backend array to multi-line text
- Users can edit routing rules line by line in textarea
- Format: 'use_backend BackendName if condition'
✅ Complete Workflow:
1. Bulk Import: Config parsed → ACL + use_backend stored as array
2. Frontend Edit: Arrays converted to multi-line string in textarea
3. User edits ACL/use_backend rules in UI
4. Save: Textarea string → validator → array → database
5. Config Generation: Array → HAProxy config format
Example workflow:
Parse: ['use_backend API if is_api']
→ Edit UI: 'use_backend API if is_api' (textarea)
→ User edits: 'use_backend API_v2 if is_api_v2'
→ Save: ['use_backend API_v2 if is_api_v2']
→ Generate: 'use_backend API_v2 if is_api_v2' (HAProxy config)
🐛 Critical Bug Fixes:
- Fixed duplicate 'acl' prefix in generated config (was: 'acl acl Name ...')
- Fixed duplicate 'use_backend' prefix in generated config
- Added use_backend directive parsing from bulk import configs
- Fixed redirect_rules list handling (was causing .strip() error)
🔧 Parser Improvements:
- Added use_backend rules parsing (stored as list like ACL rules)
- Changed use_backend_rules field from str to list for consistency
- Parser now captures all use_backend directives with conditions
🎯 Config Generation Improvements:
- Smart prefix detection: only add 'acl' if not already present
- Smart prefix detection: only add 'use_backend' if not already present
- Support both legacy (string) and new (list) format for rules
- Proper JSON parsing with fallback to newline-separated format
✅ HAProxy Validation:
- Generated config now passes HAProxy validation (haproxy -c -f)
- ACL and use_backend directives in correct HAProxy format
- Routing rules properly linked with ACL conditions
Example parsed config:
acl Elasticsearch hdr(host) -i baremetal-elastic.burgan.com.tr
use_backend Elasticsearch if Elasticsearch
Tested with full config including multiple ACLs and routing rules.
Critical security fixes:
- Add admin-only checks for user CRUD operations
- Add admin-only checks for role CRUD operations
- Add admin-only checks for role assignment operations
- Add permission check for agent script generation
- Fix auth_middleware to include is_admin flag in user context
- Hide user/role management buttons from non-admin users in UI
- Add 'View Only' labels for viewer users
Security improvements:
- Prevent viewer users from creating/editing/deleting users
- Prevent viewer users from creating/editing/deleting roles
- Prevent viewer users from assigning roles to users
- Backend API endpoints now properly check admin status
- Frontend UI now hides admin-only actions from viewers
Public release changes:
- Remove company-specific registry URLs from build-images.sh
- Update registry to generic example: your-registry.example.com
Affected endpoints:
- POST /api/users (create user) - admin only
- PUT /api/users/{id} (update user) - admin only
- DELETE /api/users/{id} (delete user) - admin only
- POST /api/roles (create role) - admin only
- PUT /api/roles/{id} (update role) - admin only
- DELETE /api/roles/{id} (delete role) - admin only
- POST /api/users/{id}/roles (assign roles) - admin only
- POST /api/agents/generate-install-script - permission check
- Remove duplicate Statistics section (already covered in Dashboard)
- Update Table of Contents to remove Statistics link
- Keep Statistics & Monitoring in API Reference (different context)
Major improvements:
- Add comprehensive Table of Contents (15 sections with clickable links)
- Reorganize structure: Screenshots after Features (better UX)
- Modernize System Architecture diagram (3-layer design, dark mode optimized)
- Simplify Agent Version Update Flow (user vs automatic actions)
- Add visual Installation selection panel (Docker vs Kubernetes)
- Expand Project Structure (150+ files documented)
- Restructure sections: 'Getting Started' (usage) vs 'Installation' (setup)
- Add Role-Based User Management to features
- Remove redundant sections (Advanced Setup, Coming Soon notes)
- Improve all diagrams for readability and modern look
- Fix all Table of Contents anchor links
- Add 18 production screenshots with descriptions
- Add cluster_id column to agent_config_requests table
- Update config request endpoint to accept and validate cluster_id
- Frontend now sends cluster_id with config requests
- Fixes issue where agents in pools with multiple clusters get wrong config requests
Technical Details:
- Database migration adds cluster_id as nullable foreign key for backward compatibility
- Backend validates that agent belongs to requested cluster via pool_id check
- Improved logging includes cluster name for better traceability
- No impact on existing features (apply management, sync status, entity CRUD)