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
18 changes: 14 additions & 4 deletions internal/cli/home.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -249,6 +249,13 @@ func resolveHomeModel(ctx context.Context, d homeDeps) homeModel {

env, beat := collectProbes(bctx, envCh, beatCh)

// Whether the PROBE itself surfaced an environment name — the signal the
// offline-vs-no-env classifier keys on (alongside `provisioned`). Captured
// BEFORE the display-name override below: otherwise a remembered client label
// left in config without a cached namespace would masquerade as a
// probe-surfaced environment and flip the no-env installer path to Offline.
probeNamedEnv := env.name != ""

// The environment's display name is the remembered client name (e.g.
// "acme-01") — the friendly, per-client identity provisioned on this machine.
// Prefer it over whatever the probe surfaced, which is the Helm RELEASE name
Expand DownExpand Up@@ -300,12 +307,15 @@ func resolveHomeModel(ctx context.Context, d homeDeps) homeModel {
// explain this as "runs elsewhere"). Offline vs. "no environment": it's an
// environment we just can't reach (offline) if EITHER this machine is
// PROVISIONED — a cached active-client namespace, the same signal the
// probe's ownership gate uses — OR the probe itself surfaced an environment
// probe's ownership gate uses — OR the PROBE itself surfaced an environment
// name. Adding the provisioned test (not name alone) is the fix for a
// provisioned-but-unnamed profile that used to misread as "no environment /
// run the installer"; keeping the name test preserves the case where the
// probe surfaced a name without one being cached.
if provisioned || env.name != "" {
// run the installer"; keeping the probe-name test preserves the case where
// the probe surfaced a name without one being cached. It must be the
// probe's own name (probeNamedEnv), NOT the post-override env.name — a
// remembered display label with no cached namespace is not evidence of a
// reachable environment and must fall through to the installer path.
if provisioned || probeNamedEnv {
m.state = homeOffline
m.fullMenu = true
} else {
Expand Down
18 changes: 18 additions & 0 deletions internal/cli/home_test.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -381,6 +381,24 @@ func TestResolveHomeModel_PrefersRememberedNameOverReleaseName(t *testing.T) {
}
}

// TestResolveHomeModel_LeftoverNameNoNamespaceIsNoEnv guards the offline-vs-no-env
// classifier against the display-name override: a leftover ActiveClientName/ID
// with NO cached namespace (provisioned=false) is NOT a reachable environment and
// must fall through to the no-env installer path, not Offline. The split keys off
// the namespace + the PROBE's own surfaced name — never the remembered label that
// resolveHomeModel writes onto env.name for display. Mutation guard: classify on
// env.name (post-override) instead of probeNamedEnv and this flips to homeOffline.
func TestResolveHomeModel_LeftoverNameNoNamespaceIsNoEnv(t *testing.T) {
d := baseDeps()
d.probeEnv = func(context.Context) envProbe { return envProbe{local: localNoRelease} } // probe surfaced no name
// Not provisioned (no cached namespace), but a stale client id lingers in config.
d.rememberedClient = func() (bool, string) { return false, "stale-id" }
m := resolveHomeModel(context.Background(), d)
if m.state != homeNoEnv {
t.Fatalf("leftover name without a cached namespace must be homeNoEnv (installer path), got state %d (envName %q)", m.state, m.envName)
}
}

// TestResolveHomeModel_PassesThroughFields checks the model carries email, name,
// and compute from the probes into the render input.
func TestResolveHomeModel_PassesThroughFields(t *testing.T) {
Expand Down
Loading