Skip to content

feat(ui): a failed connect's error page with the connect's stages (D-114) - #77

Merged
hans-fischer merged 7 commits into
mainfrom
feat/failed-connect-page
Oct 22, 2026
Merged

hans-fischer merged 7 commits into
mainfrom
feat/failed-connect-page

Conversation

@hans-fischer

Copy link
Copy Markdown
Contributor

Cogpit now shows a failed connect's own error page instead of the welcome page, and every connect, failed or not, carries its stages in Connection Updates. This builds the owner's AW17 (his decision of 2026-10-22, D-114) and AW13 from the alpha walk, and fixes AW18.

Cause

  • After a failed restore the engine set Welcome for any failed connect, so the welcome page covered the workspace.
  • That page showed the raw error chain in its status line, with no Connect Again and no connection log. D-97's placeholder, which has those buttons, sat under the welcome page and never showed.
  • The placeholder's one-line "Could not connect to : " was centred at full width, so it drew past the view over the navigator. The welcome page hid the rest, which left a clipped "Could not" at the navigator's edge (AW18).
  • The window tests' fake engine never derived Welcome, so TestAFailedConnectStaysOnItsCluster passed over the bug.

Fix

  • cluster/connectstages.go measures each connect in stages: kubeconfig valid and complete, a credential plugin's login, DNS, TCP, TLS, and the API server's login and first request.
    • DNS, TCP and TLS come from client-go's own first request (GET /version), traced with net/http/httptrace.
    • So Cogpit opens no extra connection and does no extra lookup, and behind a proxy the stages name the proxy.
  • The engine keeps the stages in each attempt and in the connection log's file, and in UIState.ConnectFailure for a failed connect. Connection.Error is the failed stage's sentence; the whole chain stays in the log.
  • The window's error page shows over the workspace whether or not a tab is open. It uses the welcome page's logo and background, says it is an error page, and has Connect Again and Show Connection Updates.
  • Connection Updates shows the stages for every connect, and Copy includes them.
  • The welcome page drops "Other clusters". "Your clusters" appears on a first start only, when neither the hotbar nor Recent has a row.
  • The view's placeholder no longer carries the failure and stays inside the view.

Decisions (the lead's, open to revision; details in D-114)

  • Stages are measured on client-go's own request, not on a probe of Cogpit's own: no extra traffic, and an honest picture behind a proxy.
  • A credential plugin's login is its own stage, before DNS, because client-go runs it before it dials.
  • The error line is the failed stage's sentence. Stage texts hold paths, hosts, addresses and the plugin's program name, never a credential; proxy and user passwords show as •••.
  • Help › Welcome over the error page leaves the failed cluster disconnected, as Disconnect does.

Tests

  • Failing before the change: the window's TestBeforeAFailedConnectShowsNotTheWelcomePage and TestBeforeThePlaceholderStaysInsideTheView (AW18: the line spanned x 128 to 1601, the view 289 to 1440), and the engine's TestBeforeARestoreThatFailsShowsTheErrorPage.
  • New cluster tests: success; DNS through a fake resolver; a missing certificate; a lookup failure; a refused port; an unknown CA; a 401; a proxy, open and refused. None touch the network: loopback servers, the testkit's proxy, and a resolver over net.Pipe.
  • New engine and window tests are listed in D-114.
  • Locally: go build ./..., go vet (plain, kind, envtest, standby), golangci-lint (0 issues), gosec (0), make cyclo, make test-ui (1181 tests), the cluster, engine, commands, mcp and app packages, -race on the stage and connect-log tests, go run ./hack/parity.
  • Not tried: a real cluster, a real credential plugin, a SOCKS proxy, a real window.

Before and after (offscreen render, dark)

Before After

Connection Updates with the stages:

…outlined

The owner's alpha walk of 2026-10-22 on v0.38.0 (G16):

- AW3, AW19: the window's Escape knew the palette, the notifications, a
  settings page and the drawer only, so over a dialog it closed the drawer
  behind it or did nothing. Every overlay now registers what Escape does
  over it as it shows (escape.go: onEscape, onShown); the window's escape
  runs the top one's, an overlay without one takes the key. Every Fyne
  dialog is shown through sh.showDialog (Escape is its Dismiss), a framed
  dialog hides (its SetOnClosed answers no), the pop-ups, the palette, the
  notifications, the MCP details and the top bar's menus close.
- Fyne hands a key to the focused widget only: the fields of Cogpit's
  dialogs are types that pass an Escape on (fieldEntry, fieldSelectEntry,
  fieldCheck, fieldSlider, secretEntry), so Escape cancels a dialog
  whatever field has the keyboard.
- AW4: a list's search is cleared and the table gets the keys; the find bar
  closes from its fields and from the editor (yamlview's OnEscape). D-57's
  "any other search" had been the navigator's only.
- AW2: Escape on an open dropdown's list takes the keyboard off the field,
  and a dropdown with the keyboard passes Escape on.
- AW1: a closed dropdown draws an entry's outline; the field outline token
  is raised to 2:1 on every surface in both themes, the wells' and cards'
  edges keep the old value as colorHairline.

TestEveryDialogTakesEscape reads the sources for a dialog or pop-up shown
past the mechanism. D-116 and D-104 record the lead's decisions; G16,
ui-parity, usage, architecture, conventions and the design language say so.
The owner's alpha walk (AW12): a click below a list's rows closed the
drawer about a second later, × and Escape at once. Fyne's driver holds
every tap on a fyne.DoubleTappable for the double-click interval before
it calls Tapped (internal/driver/glfw/window.go,
mouseClickedHandleTapDoubleTap; NSEvent.doubleClickInterval on macOS,
0.5 s by default), and the list's table was one for its header
separators' double click, which fits a column.

The table now counts that double click itself, as the tab bar and the
navigator do (doubleClickTime and the tab bar's clock), and is no
DoubleTappable: every click on it acts at its release. Rows and headers
were not held: their cells take their own taps.

TestListClicksAreNotHeld clicks a row, a header, a header separator and
the area below the rows as the driver finds the object under the pointer
and fails on a DoubleTappable target; it and the reworked
TestDoubleClickSeparatorFitsColumn fail before the change. D-106's GW1
table records the cause and the lead's choice; G16, ui-parity and
architecture follow.
The welcome page's cluster rows were a fyne.DoubleTappable, their double
click doing what a click does, so Fyne's driver held every click on them
for the double-click interval (AW12's cause, found on the table first).
The row takes clicks only now.

Without the hold, a double click's second click reaches the row again,
which the page has rebuilt by then for the cluster connecting: a second
cluster.connect would join the run under way but end the first one's
wait with errConnectInBackground, an error toast naming another cluster,
and a login program not allowed yet would be reviewed twice. The page
therefore does nothing for a cluster whose connect it began and that has
not returned (pending, from before the review or the dispatch to the
engine's answer) or that the window shows connecting.

TestWelcomeRowConnectsOnce fails on the old row (held) and on a row
without the page's guard (connected twice). D-106 records the choice
and the clicks left held (the sync picker's rows, the log tab's head
row) with why; G16's AW12 entry follows.
…114)

The owner's AW17, AW13 and AW18 of the alpha walk (2026-10-22, D-114).

A chosen cluster's failed connect, the restore's or a click's, now shows
that cluster's error page over the workspace whether or not a tab is
open; the welcome page shows only without a chosen cluster. The page is
the welcome page's look: the logo, that it is an error page, the cause
in a sentence under the stage it failed in, the connect stage by stage,
Connect Again and Show Connection Updates.

The cluster layer measures every connect in stages: the kubeconfig, a
credential plugin's login, DNS with its addresses, TCP to the address
and port (or the proxy's), TLS and the API server's answer. DNS, TCP
and TLS come from client-go's own first request through
net/http/httptrace, so Cogpit opens no connection of its own. The
stages reach the connection log (an attempt's stages, a record each in
its file), UIState.ConnectFailure and the ConnectError; the
connection's error is the failed stage's sentence, the chain stays in
the log. Connection Updates shows each connect's stages.

The welcome page lists the hotbar and Recent only, the kubeconfigs'
clusters as "Your clusters" on a first start alone (AW13). The view's
placeholder no longer says the failure and fits the view with an
ellipsis: its long line drew a clipped "Could not" over the navigator
(AW18). The window tests' fake engine derives the welcome page where
the connection changes, as the engine does.
TestWelcomeRowConnectsOnce failed on the stacked tree for two reasons of
D-114's commit, not of the guard. The window tests' fake engine now
derives the welcome page as the engine does, which hides it while the
shown cluster connects, so the row it waited to see rebuilt never was.
And the page has no "Other clusters" any more (AW13): once a cluster is
recent, the others' rows went, and the later steps found none.

The scene puts every cluster on the hotbar, so each keeps its row, and
keeps the page up after each connect the test shows, so that a click on
the connecting cluster's row is still checked; a last step checks that
the page hides while the shown cluster connects. The error page's test
checks that Connect Again, which goes through the welcome page's
connect, connects once for a double press.
@hans-fischer
hans-fischer force-pushed the feat/failed-connect-page branch from 9312d02 to db73e2c Compare October 22, 2026 16:04
@hans-fischer
hans-fischer merged commit 011d502 into main Oct 22, 2026
@hans-fischer
hans-fischer deleted the feat/failed-connect-page branch October 22, 2026 16:36
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