|
| 1 | +# First-Start Mode Feature |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The KEA DHCP Lease Manager now includes a "first-start" mode that prevents the application from hanging during startup when the configuration is unconfigured or set to default values. |
| 6 | + |
| 7 | +## Problem Solved |
| 8 | + |
| 9 | +**Before:** When starting the application with a blank or default configuration pointing to `localhost`, the GUI would hang for a long time trying to connect to a non-existent KEA server, resulting in poor user experience. |
| 10 | + |
| 11 | +**After:** The application now detects unconfigured state and immediately shows the configuration dialog without attempting to connect to KEA, providing a smooth first-time setup experience. |
| 12 | + |
| 13 | +## How It Works |
| 14 | + |
| 15 | +### Backend Detection (`app.py`) |
| 16 | + |
| 17 | +The application now includes an `is_config_valid()` function that detects if the configuration is in an unconfigured state: |
| 18 | + |
| 19 | +```python |
| 20 | +def is_config_valid(): |
| 21 | + """ |
| 22 | + Check if the configuration is valid (not in first-start/unconfigured state). |
| 23 | + Returns True if config is properly set up, False if it's still using defaults. |
| 24 | + """ |
| 25 | + kea_url = config['kea']['control_agent_url'] |
| 26 | + |
| 27 | + # Check if using default localhost URL or empty URL |
| 28 | + if not kea_url or kea_url.strip() == '': |
| 29 | + return False |
| 30 | + |
| 31 | + # Check if it's still pointing to localhost (default config) |
| 32 | + if 'localhost' in kea_url.lower() or '127.0.0.1' in kea_url: |
| 33 | + return False |
| 34 | + |
| 35 | + return True |
| 36 | +``` |
| 37 | + |
| 38 | +### Unconfigured State Handling |
| 39 | + |
| 40 | +When the configuration is detected as invalid: |
| 41 | + |
| 42 | +1. **Health Check Endpoint** (`/api/health`): |
| 43 | + - Returns `status: 'unconfigured'` instead of attempting connection |
| 44 | + - No timeout or hanging |
| 45 | + - HTTP 200 response with clear message |
| 46 | + |
| 47 | +2. **Leases Endpoint** (`/api/leases`): |
| 48 | + - Returns `unconfigured: true` flag |
| 49 | + - Friendly error message directing user to configure |
| 50 | + - No KEA connection attempt |
| 51 | + |
| 52 | +3. **Subnets Endpoint** (`/api/subnets`): |
| 53 | + - Returns empty subnets array with unconfigured flag |
| 54 | + - No KEA connection attempt |
| 55 | + |
| 56 | +### Frontend Experience (`index.html`) |
| 57 | + |
| 58 | +On page load, the application: |
| 59 | + |
| 60 | +1. **Checks health status first** before loading any data |
| 61 | +2. **Detects unconfigured state** from health response |
| 62 | +3. **Shows warning banner** with clear instructions |
| 63 | +4. **Automatically opens configuration modal** after 500ms delay |
| 64 | +5. **Skips data loading** until properly configured |
| 65 | + |
| 66 | +#### Visual Indicators |
| 67 | + |
| 68 | +- **Connection Status**: Shows "Not Configured" in red |
| 69 | +- **Warning Banner**: Yellow alert at top of page with first-time setup message |
| 70 | +- **Configuration Modal**: Opens automatically with empty/default values |
| 71 | +- **Error Messages**: Shows friendly "not configured" message instead of timeout errors |
| 72 | + |
| 73 | +## User Flow |
| 74 | + |
| 75 | +### First-Time Setup |
| 76 | + |
| 77 | +1. User starts the application with default/blank config |
| 78 | +2. Health check detects unconfigured state (instant, no timeout) |
| 79 | +3. Yellow warning banner appears at top of page |
| 80 | +4. Configuration modal opens automatically after brief delay |
| 81 | +5. User enters KEA server details and saves |
| 82 | +6. Page reloads with new configuration |
| 83 | +7. Application connects to KEA and loads data normally |
| 84 | + |
| 85 | +### Subsequent Starts |
| 86 | + |
| 87 | +- If configuration is valid (not localhost), normal startup occurs |
| 88 | +- Health check attempts connection to KEA |
| 89 | +- Data loads as expected |
| 90 | + |
| 91 | +## Configuration Validation Rules |
| 92 | + |
| 93 | +The configuration is considered **invalid/unconfigured** if: |
| 94 | + |
| 95 | +- KEA Control Agent URL is empty or blank |
| 96 | +- URL contains "localhost" (case-insensitive) |
| 97 | +- URL contains "127.0.0.1" |
| 98 | + |
| 99 | +The configuration is considered **valid** if: |
| 100 | + |
| 101 | +- URL points to a non-localhost address (e.g., `http://kea.tux42.au:8000`) |
| 102 | +- URL is properly formatted with http:// or https:// |
| 103 | + |
| 104 | +## Benefits |
| 105 | + |
| 106 | +✅ **No hanging or timeouts** on first start |
| 107 | +✅ **Clear user guidance** with automatic modal opening |
| 108 | +✅ **Instant feedback** - no waiting for connection attempts |
| 109 | +✅ **Better UX** - users know exactly what to do |
| 110 | +✅ **Prevents confusion** - clear unconfigured state vs connection errors |
| 111 | +✅ **Faster startup** - skips unnecessary connection attempts |
| 112 | + |
| 113 | +## API Changes |
| 114 | + |
| 115 | +### Health Check Response |
| 116 | + |
| 117 | +**Unconfigured State:** |
| 118 | +```json |
| 119 | +{ |
| 120 | + "status": "unconfigured", |
| 121 | + "kea_connection": "not_configured", |
| 122 | + "message": "KEA server not configured. Please update configuration." |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +**Healthy State:** |
| 127 | +```json |
| 128 | +{ |
| 129 | + "status": "healthy", |
| 130 | + "kea_connection": "ok" |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +**Unhealthy State:** |
| 135 | +```json |
| 136 | +{ |
| 137 | + "status": "unhealthy", |
| 138 | + "kea_connection": "failed", |
| 139 | + "error": "Connection refused" |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +### Leases/Subnets Response (Unconfigured) |
| 144 | + |
| 145 | +```json |
| 146 | +{ |
| 147 | + "success": false, |
| 148 | + "unconfigured": true, |
| 149 | + "error": "KEA server not configured. Please update configuration to connect." |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +## Testing |
| 154 | + |
| 155 | +To test the first-start mode: |
| 156 | + |
| 157 | +1. **Reset to default config:** |
| 158 | + ```bash |
| 159 | + cp config.yaml.template config.yaml |
| 160 | + ``` |
| 161 | + |
| 162 | +2. **Start the application:** |
| 163 | + ```bash |
| 164 | + python app.py |
| 165 | + # or in Docker |
| 166 | + docker-compose up |
| 167 | + ``` |
| 168 | + |
| 169 | +3. **Expected behavior:** |
| 170 | + - Page loads instantly (no hanging) |
| 171 | + - Yellow warning banner appears |
| 172 | + - Configuration modal opens automatically |
| 173 | + - Status shows "Not Configured" |
| 174 | + |
| 175 | +4. **Configure KEA URL:** |
| 176 | + - Enter valid KEA server URL (not localhost) |
| 177 | + - Save configuration |
| 178 | + - Page reloads and connects normally |
| 179 | + |
| 180 | +## Docker Considerations |
| 181 | + |
| 182 | +When running in Docker with volume-mounted config: |
| 183 | + |
| 184 | +```bash |
| 185 | +docker run -p 5000:5000 \ |
| 186 | + -v $(pwd)/config.yaml:/app/config/config.yaml:ro \ |
| 187 | + awkto/kea-gui-reservations:latest |
| 188 | +``` |
| 189 | + |
| 190 | +- If `config.yaml` has default localhost URL, first-start mode activates |
| 191 | +- User can configure through web UI, but changes won't persist without writable volume |
| 192 | +- For persistent config, mount as read-write: `-v $(pwd)/config.yaml:/app/config/config.yaml:rw` |
| 193 | + |
| 194 | +## Future Enhancements |
| 195 | + |
| 196 | +Possible improvements: |
| 197 | + |
| 198 | +- [ ] Add "skip localhost check" option for legitimate localhost setups |
| 199 | +- [ ] Persist "first-start complete" flag to only show banner once |
| 200 | +- [ ] Add config validation before save (test KEA connection) |
| 201 | +- [ ] Remember last successful config for rollback |
| 202 | +- [ ] Add guided setup wizard with multiple steps |
0 commit comments