feat(cli): add firewalls and elastic-ips commands (PD-6077) by LanusseMorais · Pull Request #91 · latitudesh/cli · GitHub
Skip to content

feat(cli): add firewalls and elastic-ips commands (PD-6077)#91

Open
LanusseMorais wants to merge 2 commits into
mainfrom
PD-6077-cli-network-firewalls-elastic-ips
Open

feat(cli): add firewalls and elastic-ips commands (PD-6077)#91
LanusseMorais wants to merge 2 commits into
mainfrom
PD-6077-cli-network-firewalls-elastic-ips

Conversation

@LanusseMorais

@LanusseMorais LanusseMorais commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the firewalls and elastic-ips command groups (full CRUD + firewall assignments), built on the Go SDK.

  • lsh firewallslist, get, create, update, delete + assignments list/create/delete
  • lsh elastic-ipslist, get, create, update, delete
  • Interactive details for firewalls: Enter on a list row shows the rules expanded
  • Positional ids, ls/rm aliases, flat output for mutations, -o json/yaml/csv + --query + --profile everywhere
  • Local validation: --status enum on elastic-ips list; firewalls update requires --name and/or a non-empty --rules

Known limitations

  • elastic-ips create requires --project and --server — the API allocates the IP in the server's region
  • Assignment create: the SDK does not map the response envelope yet, so the confirmation falls back to the request inputs (no assignment id shown)
  • --wait on elastic-ips create deferred (API returns 202 with id: nil) — see PD-6077 comments

Testing

Clone & checkout

git clone https://github.com/latitudesh/cli.git && cd cli
git checkout PD-6077-cli-network-firewalls-elastic-ips

Build & unit tests

go build -o lsh .
go test ./...

Try the commands (requires an authenticated profile — ./lsh login)

# firewalls
./lsh firewalls list
echo '[{"from":"ANY","to":"ANY","protocol":"TCP","port":"22","description":"SSH"}]' > rules.json
./lsh firewalls create --name review-test --project <project> --rules @rules.json
./lsh firewalls get <fw_id>
./lsh firewalls update <fw_id> --name review-test-renamed
./lsh firewalls assignments create --firewall <fw_id> --server <sv_id>
./lsh firewalls assignments list --firewall <fw_id>
./lsh firewalls assignments delete <fwasg_id> --firewall <fw_id>
./lsh firewalls delete <fw_id>

# elastic ips
./lsh elastic-ips create --project <project> --server <sv_id>
./lsh elastic-ips list --status active -o json
./lsh elastic-ips update <eip_id> --server <other_sv_id>
./lsh elastic-ips delete <eip_id>

Greptile Summary

This PR introduces complete CRUD command groups for firewalls and elastic-ips (including firewall assignment management), backed by the Go SDK, with interactive TUI tables, enter-to-details drill-down, and thorough unit tests for all request-building paths.

  • lsh firewallslist, get, create, update, delete with a rich enter-to-details view that expands per-rule fields; an assignments sub-group (list, create, delete) rounds out the surface.
  • lsh elastic-ipslist (with --status enum validation), get, create, update, delete; the create path documents the 202/async limitation and defers --wait support.
  • Renderer infrastructureDetailFielder/DetailViewer interfaces, RenderDetails, RunResourceTableOrdered, and a scrollable viewport in ResourceDetailsModel are added to support the new resource detail views.

Confidence Score: 4/5

Safe to merge once the elastic-IP TUI label issue (routing to the pre-existing "IP Addresses" title instead of "Elastic IPs") is addressed; all command logic, validation, and SDK wiring look correct.

The elastic-IP list and get commands render under the hardcoded "IP Addresses" / "IP Details" labels because isIPData fires first — every user who runs elastic-ips list or elastic-ips get sees the wrong resource name in the interactive view. This is a visible, reproducible UI regression introduced by the new ElasticIP.TableRow() returning address and family keys that trigger the legacy IP-address dispatch path.

internal/renderer/bubbletea.go — the isIPData dispatch runs before the DetailFielder check, swallowing elastic IPs into the old "IP Addresses" render path and showing incorrect titles.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant CLI as cobra Command
    participant Builder as buildXxxRequest
    participant SDK as latitudesh-go-sdk
    participant Renderer as utils.Render/RenderDetails

    User->>CLI: lsh firewalls list
    CLI->>Builder: buildListRequest(cmd)
    Builder-->>CLI: ListFirewallsRequest
    CLI->>SDK: client.Firewalls.List(ctx, filter, ...)
    SDK-->>CLI: []FirewallData
    CLI->>Renderer: utils.Render(firewalls.GetData())
    Renderer->>Renderer: isIPData? → no
    Renderer->>Renderer: DetailFielder? → yes (Firewall)
    Renderer-->>User: TUI table (enter → rule details)

    User->>CLI: lsh firewalls get fw_x
    CLI->>SDK: client.Firewalls.Get(ctx, id, ...)
    SDK-->>CLI: FirewallData
    CLI->>Renderer: utils.RenderDetails(firewall.GetData())
    Renderer->>Renderer: interactive + DetailFielder? → yes
    Renderer-->>User: Detail sheet (ID/Name/Project/Rules/Rule N)

    User->>CLI: lsh elastic-ips list --status active
    CLI->>Builder: buildListRequest(cmd)
    Builder-->>CLI: ListElasticIpsRequest (validated status)
    CLI->>SDK: client.ElasticIps.ListElasticIps(ctx, request, ...)
    SDK-->>CLI: []ElasticIPData
    CLI->>Renderer: utils.Render(ips.GetData())
    Renderer->>Renderer: isIPData? → yes (address+family keys)
    Renderer-->>User: TUI table (title: "IP Addresses" ← wrong label)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant CLI as cobra Command
    participant Builder as buildXxxRequest
    participant SDK as latitudesh-go-sdk
    participant Renderer as utils.Render/RenderDetails

    User->>CLI: lsh firewalls list
    CLI->>Builder: buildListRequest(cmd)
    Builder-->>CLI: ListFirewallsRequest
    CLI->>SDK: client.Firewalls.List(ctx, filter, ...)
    SDK-->>CLI: []FirewallData
    CLI->>Renderer: utils.Render(firewalls.GetData())
    Renderer->>Renderer: isIPData? → no
    Renderer->>Renderer: DetailFielder? → yes (Firewall)
    Renderer-->>User: TUI table (enter → rule details)

    User->>CLI: lsh firewalls get fw_x
    CLI->>SDK: client.Firewalls.Get(ctx, id, ...)
    SDK-->>CLI: FirewallData
    CLI->>Renderer: utils.RenderDetails(firewall.GetData())
    Renderer->>Renderer: interactive + DetailFielder? → yes
    Renderer-->>User: Detail sheet (ID/Name/Project/Rules/Rule N)

    User->>CLI: lsh elastic-ips list --status active
    CLI->>Builder: buildListRequest(cmd)
    Builder-->>CLI: ListElasticIpsRequest (validated status)
    CLI->>SDK: client.ElasticIps.ListElasticIps(ctx, request, ...)
    SDK-->>CLI: []ElasticIPData
    CLI->>Renderer: utils.Render(ips.GetData())
    Renderer->>Renderer: isIPData? → yes (address+family keys)
    Renderer-->>User: TUI table (title: "IP Addresses" ← wrong label)
Loading

Reviews (2): Last reviewed commit: "refactor(cli): self-describing detail vi..." | Re-trigger Greptile

Comment thread internal/renderer/bubbletea.go Outdated
@LanusseMorais

Copy link
Copy Markdown
Collaborator Author

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