Skip to content

feat: SG group CRUD, network/subnet CRUD, port listing, LB fix#18

Merged
larkly merged 5 commits intomainfrom
feat/sg-network-crud
Mar 26, 2026
Merged

feat: SG group CRUD, network/subnet CRUD, port listing, LB fix#18
larkly merged 5 commits intomainfrom
feat/sg-network-crud

Conversation

@larkly
Copy link
Copy Markdown
Owner

@larkly larkly commented Mar 26, 2026

Summary

Major feature batch: SG group CRUD, network/subnet CRUD, router tab with interface management, server stop/start/lock/unlock, port listing, LB fix, vim key fix in text inputs.

Server Actions

  • Stop/Start (o): toggle between ACTIVE and SHUTOFF, with bulk support
  • Lock/Unlock (ctrl+l): prevent/allow modifications, with bulk support

Router Tab (full CRUD)

  • List: Name, Status, External Gateway, Routes count with sorting and auto-refresh
  • Detail: Properties + navigable interfaces list + static routes
  • Create (ctrl+n): Name, external network picker, admin state
  • Delete (ctrl+d): Confirmation modal, works from list or detail
  • Add Interface (ctrl+a from detail): Subnet picker modal
  • Remove Interface (ctrl+t from detail): Confirmation on selected interface
  • Backend: ListRouters, GetRouter, CreateRouter, DeleteRouter, AddRouterInterface, RemoveRouterInterface, ListRouterInterfaces

Security Group CRUD

  • Create group (ctrl+n on group level): modal with name + description fields
  • Delete group (ctrl+d on group level): confirmation modal
  • Context-sensitive keybindings: group level = group create/delete, rules level = rule create/delete (existing)
  • Backend: CreateSecurityGroup(), DeleteSecurityGroup() in secgroups.go

Network/Subnet CRUD

  • Create network (ctrl+n on network level): modal with name + admin state (Up/Down) cycle picker
  • Delete network (ctrl+d on network level): confirmation modal
  • Create subnet (ctrl+n in subnet navigation): modal with name, CIDR, IP version (4/6), gateway IP, DHCP toggle
  • Delete subnet (ctrl+d in subnet navigation): confirmation modal
  • Re-added subnet navigation with cursor highlighting (needed for subnet-level actions)
  • Backend: CreateNetwork(), DeleteNetwork(), CreateSubnet(), DeleteSubnet(), SubnetCreateOpts

Port Listing (read-only)

  • Ports shown in expanded network view below subnets
  • Displays: name/ID, MAC address, fixed IPs, device owner
  • Backend: ListPorts() with network ID filter in new ports.go

LB Name Fix

  • Name column now uses remaining terminal width instead of fixed 28 chars
  • Fixed truncate() to properly handle ellipsis (was producing strings longer than intended)

Vim j/k Fix

  • All form/modal text inputs no longer trigger vim navigation (j=down, k=up) when typing
  • Fixed in all 8 form components: servercreate, volumecreate, keypaircreate, sgcreate, sgrulecreate, networkcreate, subnetcreate, routercreate

PRD Update

  • Backlog section marked as complete
  • Phase 3 docs updated with volume create, keypair create/detail, SG rule create, network browser
  • Keybinding tables updated
  • Project structure updated with new packages

Verification checklist

Security Group Create (ctrl+n on group level)

  • On security groups tab, with cursor on a group header (NOT in rules), status bar shows "^n create group"
  • ctrl+n opens "Create Security Group" modal
  • Tab/arrows navigate Name and Description fields
  • ctrl+s or Submit creates the group
  • Validation: empty name shows error
  • Status bar shows sticky "✓ Created security group " on success
  • esc cancels and closes the modal
  • New group appears in list after auto-refresh

Security Group Delete (ctrl+d on group level)

  • On security groups tab, with cursor on a group header (NOT in rules), ctrl+d opens delete confirmation
  • Confirmation shows group name and warns about rules being deleted
  • y confirms and deletes, n/esc cancels
  • "default" security group deletion shows API error (expected — OpenStack prevents this)
  • Status bar shows sticky success message after delete

Context-Sensitive Security Group Keybindings

  • On group level: ctrl+n = create group, ctrl+d = delete group
  • In rules (after expanding and navigating into rules): ctrl+n = add rule, ctrl+d = delete rule
  • Status bar hints update correctly for each context

Network Create (ctrl+n on network level)

  • On networks tab, with cursor on a network (NOT in subnets), status bar shows "^n create network"
  • ctrl+n opens "Create Network" modal
  • Name field and Admin State (Up/Down) cycle picker work
  • ←→ cycles admin state between Up and Down
  • ctrl+s or Submit creates the network
  • Validation: empty name shows error
  • Status bar shows sticky success message
  • New network appears in list after auto-refresh

Network Delete (ctrl+d on network level)

  • ctrl+d on a network opens delete confirmation
  • Confirmation warns about subnets being deleted
  • y confirms and deletes, n/esc cancels
  • Networks with active ports show API error (expected)

Subnet Navigation

  • Expanding a network with Enter shows subnets
  • Down arrow from last network row enters subnet navigation (if expanded and has subnets)
  • Selected subnet shows ▸ prefix and highlight
  • Up from first subnet returns to network header
  • Down from last subnet moves to next network
  • esc exits subnet navigation back to networks
  • Status bar hints change when entering/exiting subnet navigation

Subnet Create (ctrl+n in subnet navigation)

  • In subnet navigation, ctrl+n opens "Create Subnet in " modal
  • Fields: Name, CIDR, IP Version (IPv4/IPv6), Gateway IP, DHCP (Enabled/Disabled)
  • ←→ cycles IP version and DHCP toggles
  • CIDR is required, name is optional
  • ctrl+s or Submit creates the subnet
  • Status bar shows "✓ Created subnet in " on success

Subnet Delete (ctrl+d in subnet navigation)

  • In subnet navigation, ctrl+d on a subnet opens delete confirmation
  • Confirmation shows subnet name and parent network name
  • y confirms and deletes

Port Listing (read-only)

  • Expanding a network shows ports below subnets
  • Ports display: name (or ID prefix), MAC address, IPs, device owner
  • Ports are not selectable/navigable (display only)
  • Ports from compute (device_owner: compute:nova) show correctly

LB Name Column

  • Load balancer list shows full names without truncation on wide terminals
  • Names truncate gracefully with "..." on narrow terminals
  • Name column grows/shrinks with terminal resize

Help Overlay (?)

  • Security Groups section shows context-sensitive hint: "create group (or add rule in rules)"
  • Networks section shows context-sensitive hint: "create network (or subnet in subnets)"

General

  • go build ./... passes
  • go vet ./... passes
  • go test ./... passes
  • No regressions in existing security group rule create/delete
  • No regressions in existing network expand/collapse
  • Modals (sgCreate, networkCreate, subnetCreate) properly intercept keys

Server Stop/Start (o key)

  • ACTIVE server: press o → confirm "stop" → server goes to SHUTOFF
  • SHUTOFF server: press o → confirm "start" → server goes to ACTIVE
  • Bulk: select multiple servers → o → stops/starts based on first server status
  • Help overlay shows o stop/start in Server List and Server Detail sections

Server Lock/Unlock (ctrl+l)

  • Unlocked server: press ctrl+l → confirm "lock" → 🔒 icon appears on next refresh
  • Locked server: press ctrl+l → confirm "unlock" → 🔒 icon disappears
  • Bulk: select multiple → ctrl+l → locks/unlocks based on first server
  • Help overlay shows ctrl+l lock/unlock in Server List and Server Detail sections

Router List (Routers tab)

  • "Routers" tab appears in tab bar
  • List shows routers with Name, Status, External Gateway (IP or "none"), Routes count
  • Up/down navigates, s/S sorts
  • Name column uses flex width (not truncated on wide terminals)
  • Auto-refresh works
  • R force-refreshes the list

Router Detail (enter from router list)

  • Enter opens detail showing Name, ID, Status, Admin State, Description
  • External Gateway shows network name + IP (or "none")
  • Interfaces section lists connected subnets with IP and port ID
  • Up/down scrolls and moves interface cursor
  • Static routes shown if any
  • esc returns to router list

Router Create (ctrl+n from router list)

  • ctrl+n opens "Create Router" modal
  • Name field (text input, vim j/k guarded)
  • External Network inline picker (type-to-filter from external networks)
  • Admin State cycle picker (Up/Down)
  • ctrl+s or Submit creates the router
  • Validation: empty name shows error
  • Status bar shows sticky success message

Router Delete (ctrl+d)

  • ctrl+d from router list opens delete confirmation
  • ctrl+d from router detail opens delete confirmation
  • Confirmation warns about interfaces being removed
  • After delete from detail, navigates back to list

Router Add Interface (ctrl+a from router detail)

  • ctrl+a opens subnet picker modal
  • Subnet picker shows all subnets with name + CIDR
  • Up/down navigates, enter selects
  • On select, adds subnet as router interface
  • Status bar shows "✓ Added interface to "
  • esc closes picker without adding

Router Remove Interface (ctrl+t from router detail)

  • Navigate to an interface in the detail view
  • ctrl+t opens remove confirmation
  • y confirms and removes interface
  • Status bar shows success message

Vim j/k Fix in Text Inputs

  • All form/modal text inputs accept j/k/h/l/q/s as normal characters
  • Tab/ShiftTab still navigate between fields
  • Enter still advances to next field
  • Esc still cancels/closes
  • Fixed in: servercreate, volumecreate, keypaircreate, sgcreate, sgrulecreate, networkcreate, subnetcreate, routercreate

Help Overlay Updates

  • Routers section appears with all keybindings
  • Server sections include o stop/start and ctrl+l lock/unlock

larkly added 5 commits March 26, 2026 02:33
…pdate

Security Group CRUD:
  - Create security group (ctrl+n on group level): name + description modal
  - Delete security group (ctrl+d on group level): confirmation modal
  - Context-sensitive keybindings: group level = group CRUD, rules = rule CRUD
  - Backend: CreateSecurityGroup(), DeleteSecurityGroup()

Network/Subnet CRUD:
  - Create network (ctrl+n on network level): name + admin state modal
  - Delete network (ctrl+d on network level): confirmation modal
  - Create subnet (ctrl+n in subnet navigation): CIDR, IP version, gateway, DHCP
  - Delete subnet (ctrl+d in subnet navigation): confirmation modal
  - Re-added subnet navigation with cursor highlighting
  - Backend: CreateNetwork(), DeleteNetwork(), CreateSubnet(), DeleteSubnet()

Port Listing:
  - Read-only port display in expanded network view
  - Shows port name, MAC address, IPs, device owner
  - Backend: ListPorts() with network ID filter

LB name fix:
  - Name column now uses remaining terminal width instead of fixed 28 chars
  - Fixed truncate function to properly handle ellipsis

PRD update:
  - Updated backlog as complete, added new features to Phase 3 docs
  - Updated keybindings tables and project structure
After deleting a security group, the next group at the same index
would inherit the expanded state because expansions were tracked by
array index. Changed to track by group ID so expansions survive
list reordering. Also clamps cursor when the list shrinks.
All form/modal text inputs were intercepting j/k as vim-style up/down
navigation because Keys.Up/Down include "k"/"j" bindings. When a text
input field has focus, only intercept Tab/ShiftTab/Enter/Esc/ctrl+s
for navigation — route all other keys to the text input.

Fixed in all 7 form/modal components:
- servercreate, volumecreate, keypaircreate (full-view forms)
- sgcreate, sgrulecreate, networkcreate, subnetcreate (modal overlays)
Down arrow only entered subnet navigation from the last network
because the condition checked cursor < len-1 first (always true
except at the end). Reversed priority: check if current network
is expanded with subnets first, then fall through to next network.

Also switched expanded map from int index to network ID (matching
the secgroupview fix) so expansions survive list reordering, and
added cursor clamping on data refresh.
When a network is expanded but has no subnets, there was no way to
enter subnet navigation to trigger ctrl+n for subnet create. Now
ctrl+n creates a subnet when the network is expanded (regardless of
whether you're in subnet navigation), and creates a network only
when collapsed. Status bar hints update to reflect context.
@larkly larkly merged commit 618a8f7 into main Mar 26, 2026
@larkly larkly deleted the feat/sg-network-crud branch March 26, 2026 01:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant