Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 117 additions & 17 deletions PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
|-------|--------|-------|
| Phase 1: MVP | ✓ Complete | Cloud connection, server CRUD, modals, help |
| Phase 2: Extended Compute | ✓ Complete | All actions, console log, resize, bulk ops, action history |
| Phase 3: Additional Resources | ✓ Complete | Tabbed navigation, volumes, floating IPs, security groups, key pairs |
| Phase 3: Additional Resources | ✓ Complete | Tabbed navigation, volumes, floating IPs, security groups, key pairs, networks (CRUD), routers (CRUD) |
| Phase 4: Refactor, Octavia, Projects, Quotas | ✓ Complete | App refactor, dynamic tabs, Octavia LB tab, project switching, quota overlay |
| Phase 5: Quality of Life | Not started | SSH, clipboard, config file, Designate (DNS) |
| Phase 5: Quality of Life | Partial | Server rename, rebuild, snapshot, rescue/unrescue, image management, confirmation dialogs for all actions — done. SSH, clipboard, config file, DNS — not started |
| Phase 6: Operational | Not started | Admin views, hypervisor view, service catalog browser |

## Concerns and Considerations
Expand Down Expand Up @@ -109,6 +109,7 @@ src/
app/
app.go # Root model, New(), Init(), Update() routing, type defs
actions_server.go # Server CRUD/lifecycle actions, bulk operations
actions_image.go # Image CRUD actions
actions_resource.go # Volume, FIP, security group, keypair, LB actions
routing.go # View routing, modal updates, view change handling
render.go # View(), viewContent(), viewName()
Expand All @@ -131,10 +132,12 @@ src/
images.go # Image listing
network/
networks.go # Network listing, external networks, port lookup
routers.go # Router CRUD, interfaces, static routes
floatingips.go # Floating IP CRUD (allocate, associate, disassociate, release)
secgroups.go # Security group listing, rule create/delete
volume/
volumes.go # Volume CRUD (list, get, create, delete, attach, detach, volume types)
selfupdate/ # GitHub release self-update
loadbalancer/
lb.go # Octavia LB, listener, pool, member CRUD
quota/
Expand Down Expand Up @@ -171,8 +174,20 @@ src/
lblist.go # Load balancer table with status colors, sorting
lbdetail/
lbdetail.go # LB detail with listener/pool/member tree
serverrename/ # Server rename inline input
serverrebuild/ # Server rebuild with image picker
serversnapshot/ # Server snapshot creation
networklist/
networklist.go # Network browser with expandable subnets
networkcreate/ # Network create form
subnetcreate/ # Subnet create form
routerlist/ # Router list with sorting
routerdetail/ # Router detail with interfaces
routercreate/ # Router create form
subnetpicker/ # Subnet picker modal
sgcreate/ # Security group create form
imagelist/ # Image list with sorting
imagedetail/ # Image detail properties view
volumecreate/
volumecreate.go # Volume create form with type/AZ pickers
serverpicker/
Expand Down Expand Up @@ -286,7 +301,7 @@ src/
- Submit via button or Ctrl+S hotkey

#### Confirmation Modals
- Required for all destructive actions (delete, reboot, pause, suspend, shelve)
- Required for all server state-change actions (delete, reboot, stop/start, pause, suspend, shelve, lock/unlock, rescue/unrescue)
- Supports both single-server and bulk operations
- Focusable [y] Confirm / [n] Cancel buttons
- Navigate buttons with arrow keys, Tab, or use hotkeys directly
Expand Down Expand Up @@ -394,6 +409,8 @@ src/
- **Rule Navigation**: Down arrow enters rule list within expanded group, Up arrow exits back to group level
- **Create Rule** (`Ctrl+N` in rules): Modal with cycle pickers for direction/ethertype/protocol, port range, remote IP prefix
- **Delete Rule** (`Ctrl+D` in rules): When cursor is on a rule, confirmation modal then deletes
- **Create Security Group** (`Ctrl+N` at group level): Form with name and description
- **Delete Security Group** (`Ctrl+D` at group level): Confirmation modal
- Selected rule highlighted with `▸` prefix and background color

#### Key Pair Management
Expand All @@ -403,10 +420,23 @@ src/
- **Save Private Key** (`s` in private key view): Save generated private key to file (default `~/.ssh/<name>`, 0600 permissions), public key saved alongside as `.pub`
- **Delete** (`Ctrl+D`): Confirmation modal, works from list or detail

#### Network Browser
#### Network Management
- **Networks Tab**: Network list with Name, Status, Subnets count, Shared columns
- **Expandable Subnets**: Enter expands/collapses network to show subnet details (name, CIDR, gateway, IP version, DHCP status)
- Auto-refresh, read-only browsing
- **Create Network** (`Ctrl+N`): Form with name, admin state, shared option
- **Delete Network** (`Ctrl+D`): Confirmation modal
- **Create Subnet** (`Ctrl+N` when expanded): Form with name, CIDR, gateway, IP version, DHCP
- **Delete Subnet** (`Ctrl+D` when in subnets): Confirmation modal
- **Port Listing**: Read-only port listing per network
- Auto-refresh, sorting

#### Router Management
- **Router List**: Columns (Name, Status, External Gateway, Routes), auto-refresh, sorting
- **Router Detail** (`Enter`): Properties view with interfaces section and static routes
- **Create Router** (`Ctrl+N`): Form with name, external network selection, admin state
- **Delete Router** (`Ctrl+D`): Confirmation modal
- **Add Interface** (`Ctrl+A` from detail): Subnet picker modal
- **Remove Interface** (`Ctrl+T` from detail): Confirmation modal

#### Column Sorting
- `s` cycles sort to next visible column (ascending), `S` toggles sort direction
Expand Down Expand Up @@ -464,13 +494,52 @@ src/
- Scroll support, close with `Q` or `Esc`
- Block Storage section omitted if Cinder unavailable

### Phase 5: Quality of Life (Partial)

#### Server Rename (`r`)
- Inline rename from server list or detail view
- Text input pre-filled with current name
- Uses `servers.Update()` API

#### Server Rebuild (`Ctrl+G`)
- Rebuild server with new image, keeping same ID/IPs
- Image picker modal with type-to-filter
- Confirmation before rebuild (destructive operation)

#### Server Snapshot (`Ctrl+S`)
- Create image snapshot from running server
- Name input pre-filled with server name
- Progress shown in status bar
- Handles 409 conflict (snapshot already in progress) with friendly error

#### Rescue/Unrescue (`Ctrl+W`)
- Toggle rescue mode for broken servers
- Confirmation modal
- Rescue mode returns admin password displayed in status bar
- Supports bulk rescue operations

#### Image Management
- **Image List Tab**: Columns (Name, Status, Size, Visibility, Created), auto-refresh, sorting
- **Image Detail** (`Enter`): Full properties view
- **Delete Image** (`Ctrl+D`): Confirmation modal, works from list or detail
- **Deactivate/Reactivate**: Toggle image availability

#### Self-Update
- `--update` flag downloads latest release from GitHub
- `--no-check-update` skips automatic version check on startup
- Downloads binary for current OS/architecture with SHA256 checksum verification

### CLI Flags

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `-version` | bool | false | Print version and exit |
| `-pick-cloud` | bool | false | Always show cloud picker, even with one cloud |
| `-refresh` | int | 5 | Server list/detail auto-refresh interval in seconds |
| `--version` | bool | false | Print version and exit |
| `--pick-cloud` | bool | false | Always show cloud picker, even with one cloud |
| `--cloud NAME` | string | "" | Connect directly to named cloud, skip picker |
| `--refresh N` | int | 5 | Auto-refresh interval in seconds |
| `--idle-timeout N` | int | 0 | Pause polling after N minutes of no input (0 = disabled) |
| `--no-check-update` | bool | false | Skip automatic update check on startup |
| `--update` | bool | false | Self-update to the latest version |

### Keybindings

Expand Down Expand Up @@ -499,8 +568,14 @@ src/
| `Ctrl+O` | Soft reboot (or selected) |
| `p` | Pause/unpause (or selected) |
| `Ctrl+Z` | Suspend/resume (or selected) |
| `o` | Stop/start (or selected) |
| `Ctrl+E` | Shelve/unshelve (or selected) |
| `Ctrl+L` | Lock/unlock (or selected) |
| `Ctrl+W` | Rescue/unrescue (or selected) |
| `Ctrl+F` | Resize (modal) |
| `r` | Rename server |
| `Ctrl+G` | Rebuild with new image |
| `Ctrl+S` | Create snapshot |
| `Ctrl+A` | Assign floating IP (FIP picker modal) |
| `l` | Console log |
| `a` | Action history |
Expand All @@ -517,7 +592,11 @@ src/
| `p` | Pause/unpause |
| `Ctrl+Z` | Suspend/resume |
| `Ctrl+E` | Shelve/unshelve |
| `Ctrl+W` | Rescue/unrescue |
| `Ctrl+F` | Resize (modal) |
| `r` | Rename server |
| `Ctrl+G` | Rebuild with new image |
| `Ctrl+S` | Create snapshot |
| `Ctrl+A` | Assign floating IP (FIP picker modal) |
| `Ctrl+Y` | Confirm resize (when VERIFY_RESIZE) |
| `Ctrl+X` | Revert resize (when VERIFY_RESIZE) |
Expand Down Expand Up @@ -564,8 +643,8 @@ src/
|-----|--------|
| `↑/k` `↓/j` | Navigate groups / rules |
| `Enter` | Expand / collapse group |
| `Ctrl+N` | Add rule (when in rules) |
| `Ctrl+D` | Delete selected rule (when in rules) |
| `Ctrl+N` | Create group (or add rule when in rules) |
| `Ctrl+D` | Delete group (or rule when in rules) |
| `Esc` | Back to group level (from rules) |

#### Key Pairs
Expand All @@ -581,6 +660,19 @@ src/
|-----|--------|
| `↑/k` `↓/j` | Navigate |
| `Enter` | Expand / collapse subnets |
| `Ctrl+N` | Create network (or subnet when expanded) |
| `Ctrl+D` | Delete network (or subnet in subnets) |

#### Routers
| Key | Action |
|-----|--------|
| `↑/k` `↓/j` | Navigate |
| `Enter` | View detail (interfaces) |
| `Ctrl+N` | Create router |
| `Ctrl+D` | Delete router |
| `Ctrl+A` | Add interface (from detail) |
| `Ctrl+T` | Remove interface (from detail) |
| `Esc` | Back to list (from detail) |

#### Load Balancers
| Key | Action |
Expand All @@ -590,6 +682,13 @@ src/
| `Ctrl+D` | Delete load balancer (cascade) |
| `Esc` | Back to list (from detail) |

#### Images
| Key | Action |
|-----|--------|
| `↑/k` `↓/j` | Navigate |
| `Enter` | View detail |
| `Ctrl+D` | Delete image |

#### Console Log / Action History
| Key | Action |
|-----|--------|
Expand Down Expand Up @@ -632,13 +731,14 @@ src/

Actions available in Nova but not yet implemented, prioritized by usefulness:

#### High-value (Phase 5 candidates)
- **Rename server** — Update server name from detail view (`servers.Update`). Quick inline edit, no modal needed.
- **Rebuild** — Rebuild with new image, keeping same ID/IPs. Modal with image picker + confirmation (destructive). Uses `servers.Rebuild`.
- **Create snapshot** — Create image from running server (`servers.CreateImage`). Show progress in status bar.
#### High-value (all complete)
- ~~**Rename server**~~: ✓ Complete — `r` key, inline rename
- ~~**Rebuild**~~: ✓ Complete — `Ctrl+G`, image picker modal
- ~~**Create snapshot**~~: ✓ Complete — `Ctrl+S`, creates image from server
- ~~**Rescue/Unrescue**~~: ✓ Complete — `Ctrl+W`, toggle rescue mode

#### Medium-value (specific scenarios)
- **Rescue/Unrescue** — Boot into rescue mode for broken servers. Rare but valuable for recovery.
- **Console access (noVNC)** — Retrieve and open VNC console URL. Text console log exists but graphical console does not.
- **Get password** — Retrieve auto-generated password for Windows VMs (`servers.GetPassword`).

#### Admin-only (Phase 6)
Expand All @@ -648,7 +748,7 @@ Actions available in Nova but not yet implemented, prioritized by usefulness:
- **Reset State** — Force server into a specific state. Recovery from stuck transitions.
- **Metadata browser** — Full CRUD on server metadata key-value pairs.

### Phase 5: Quality of Life
### Phase 5: Quality of Life (remaining)
- Configuration file (`~/.config/lazystack/config.yaml`) for defaults
- Custom column selection and ordering
- Saved filters
Expand All @@ -657,7 +757,7 @@ Actions available in Nova but not yet implemented, prioritized by usefulness:
- Copy-to-clipboard for IDs, IPs
- Log/audit trail of actions taken
- Designate (DNS) tab
- Server rename, rebuild, snapshot (see Server Action Gaps above)
- Console access (noVNC URL retrieval and browser launch)

### Phase 6: Operational
- Hypervisor view (admin)
Expand Down
28 changes: 25 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,25 @@ Single binary. No runtime dependencies. Reads your standard `clouds.yaml`.

## Features

- **Server management** — list, create, delete, reboot, stop/start, pause, suspend, shelve, lock/unlock, resize with bulk operations
- **Server management** — list, create, delete, rename, rebuild, reboot, stop/start, pause, suspend, shelve, lock/unlock, rescue/unrescue, resize, snapshot, with bulk operations
- **Volume management** — list, detail, create, delete, attach (server picker), detach
- **Floating IPs** — allocate, associate, disassociate, release
- **Security groups** — create/delete groups, create/delete rules, expandable rule view
- **Networks** — create/delete networks, create/delete subnets, read-only port listing
- **Routers** — create/delete routers, add/remove interfaces (subnet picker), detail with routes
- **Key pairs** — create (RSA 2048/4096, ED25519), import with ~/.ssh/ file browser, detail view, save private key to file
- **Images** — list, detail, delete, deactivate/reactivate with status-aware coloring
- **Load balancers** (Octavia) — list, detail tree (listeners/pools/members), cascade delete
- **Project switching** — switch between accessible Keystone projects without restarting
- **Quota overlay** — compute, network, and storage quotas with color-coded progress bars
- **Confirmation dialogs** — all server state-change actions require explicit confirmation
- **Dynamic tabs** — tabs appear based on available services (no Cinder? no Volumes tab)
- **Auto-refresh** — all views refresh in the background at a configurable interval
- **Console log** and **action history** per server
- **Column sorting** on all list views
- **Client-side filtering** with `/`
- **Bulk select** with `space` for multi-server operations
- **Self-update** — `--update` flag to update to latest release
- **Solarized Dark** color scheme with status-aware coloring

## Installation
Expand Down Expand Up @@ -113,7 +116,9 @@ No additional configuration is needed. If only one cloud is defined, lazystack c
| Flag | Default | Description |
|------|---------|-------------|
| `--pick-cloud` | `false` | Always show cloud picker, even with one cloud |
| `--cloud NAME` | | Connect directly to named cloud, skip picker |
| `--refresh N` | `5` | Auto-refresh interval in seconds |
| `--idle-timeout N` | `0` | Pause polling after N minutes of no input (0 = disabled) |
| `--no-check-update` | `false` | Skip the automatic update check on startup |
| `--update` | `false` | Self-update to the latest release |
| `--version` | | Print version and exit |
Expand Down Expand Up @@ -151,8 +156,12 @@ No additional configuration is needed. If only one cloud is defined, lazystack c
| `Ctrl+Z` | Suspend / resume |
| `Ctrl+E` | Shelve / unshelve |
| `Ctrl+L` | Lock / unlock |
| `Ctrl+W` | Rescue / unrescue |
| `Ctrl+F` | Resize |
| `Ctrl+A` | Assign floating IP |
| `r` | Rename |
| `Ctrl+G` | Rebuild with new image |
| `Ctrl+S` | Create snapshot |
| `L` | Console log |
| `a` | Action history |

Expand All @@ -168,9 +177,13 @@ No additional configuration is needed. If only one cloud is defined, lazystack c
| `Ctrl+Z` | Suspend / resume |
| `Ctrl+E` | Shelve / unshelve |
| `Ctrl+L` | Lock / unlock |
| `Ctrl+W` | Rescue / unrescue |
| `Ctrl+F` | Resize |
| `Ctrl+Y` / `Ctrl+X` | Confirm / revert resize |
| `Ctrl+A` | Assign floating IP |
| `r` | Rename |
| `Ctrl+G` | Rebuild with new image |
| `Ctrl+S` | Create snapshot |
| `L` | Console log |
| `a` | Action history |
| `Esc` | Back to list |
Expand Down Expand Up @@ -234,6 +247,13 @@ No additional configuration is needed. If only one cloud is defined, lazystack c
| `Enter` | View detail tree |
| `Ctrl+D` | Delete (cascade) |

### Images

| Key | Action |
|-----|--------|
| `Enter` | View detail |
| `Ctrl+D` | Delete image |

### Create form

| Key | Action |
Expand All @@ -254,15 +274,17 @@ Built with:

```
src/internal/
app/ # Root model, routing, actions, rendering (7 files)
app/ # Root model, routing, actions, rendering (8 files)
cloud/ # Auth, service detection, project listing
compute/ # Nova: servers, flavors, keypairs, actions
image/ # Glance: images
network/ # Neutron: networks, subnets, ports, routers, floating IPs, security groups
volume/ # Cinder: volumes, volume types
loadbalancer/ # Octavia: LBs, listeners, pools, members
quota/ # Quota fetching (compute, network, storage)
selfupdate/ # GitHub release self-update
shared/ # Keys, styles, messages
ui/ # All view components (25 packages)
ui/ # All view components (38 packages)
```

## License
Expand Down
Loading