Skip to content

feat: jump from the Argo CD view into a remote managed resource, and back - #630

Open
ShmuelOps wants to merge 1 commit into
nklmilojevic:mainfrom
ShmuelOps:feat/argocd-remote-jump-1
Open

ShmuelOps wants to merge 1 commit into
nklmilojevic:mainfrom
ShmuelOps:feat/argocd-remote-jump-1

Conversation

@ShmuelOps

Copy link
Copy Markdown
Contributor

Items 1 and 2 of the proposal in #532, as agreed with @mesutoezdil, plus the marker that makes the jump discoverable. Three commits, one feature: getting from the Argo CD view to a remote object and back.

Problem

Since #570 a remote destination resolves to a kubeconfig context, but on a managed resource of a remote Application only reports where it lives and tells the user to :ctx there by hand, then find it again — four steps to look at the pod behind a Degraded row, and the same in reverse to come back.

Change

  1. on a remote managed resource jumps to it. Switch to the resolved context and, once the connection lands, open the object as a root view scoped to its name (metadata.name= field selector, same as navigate_to_target). The kind is resolved against the destination cluster at landing time, since the hub may not know the CRD; a kind the destination does not know either falls back to pods with a warning. The deferred target lives in its own slot next to the pending query / bookmark / workspace and follows the same one-at-a-time rules, cleared on a failed switch.

    The feat: Argo CD read side - Application columns, :argocd view, fleet count, ownership tree #532 rule "on a remote destination enter flashes where the object lives instead of opening a same-named object here" guarded against opening the wrong cluster's object when destinations could not be resolved. With fix: resolve Argo CD destination names against every kubeconfig context #570 they resolve to a context, so the guard becomes the jump; an unresolved destination still flashes, and a heading or source line under a remote destination still has nothing to open and says so.

  2. esc comes back. The jump records the hub context and the object the view was opened for while the view it opened is on screen. esc at that view's root switches back and, once the switch lands, reopens the Argo CD view on the same object, with the table underneath set to that kind. Tab through the default kinds in the remote cluster keeps the way back (still browsing where the jump landed); a :resource query, bookmark or workspace drops it, so esc there is an ordinary root esc. The pods fallback keeps it too.

  3. on the rows that now jump. draw_findings takes the jump predicate from the view instead of reading the finding's target; the Argo CD view marks a managed-resource row whenever its destination resolved to a context. Explain and GitOps keep the target-based rule.

No new keys, no new config. Docs: docs/features.md Argo CD view paragraph.

Tests (through handle_key)

  • argocd_view_enter_on_a_remote_resource_opens_it_in_its_context — Enter → on the row → switch armed → land_context → services scoped to the name → esc → switch back → Mode::Argocd with the same title.
  • argocd_view_enter_on_a_remote_heading_does_not_switch, argocd_remote_jump_return_is_dropped_by_a_new_root_view, argocd_remote_jump_return_survives_tab_cycling, argocd_remote_jump_unknown_kind_falls_back_to_pods_and_esc_returns.
  • argocd_view_enter_switches_to_the_alias_context_for_a_remote_name — the fix: resolve Argo CD destination names against every kubeconfig context #570 regression adapted: Enter switches to the alias, not Argo's spelling.
  • argocd_view_will_not_jump_into_a_remote_destination (unresolved) unchanged.

cargo fmt --check, cargo clippy --locked --all-targets -- -D warnings, cargo test --locked (1705) pass.

@ShmuelOps
ShmuelOps force-pushed the feat/argocd-remote-jump-1 branch from 58297b5 to fcfc129 Compare September 17, 2026 10:46
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The PR should not merge until the stale active-context case has a recovery path that actually reconnects to the remapped cluster.

Findings

  1. P1 Reconnect Advice Cannot Work

Summary

This PR adds bidirectional navigation between an Argo CD view and managed resources in remote Kubernetes contexts.

  • Resolves destination locality using cluster server identity rather than context-name equality.
  • Defers opening a remote resource until its context switch completes and preserves return navigation.
  • Marks navigable Argo CD rows with and prevents truncated summary rows from becoming jump targets.
  • Clears deferred Argo CD navigation when another root navigation takes precedence.
  • Adds extensive coverage for jumps, returns, failures, aliases, fallback kinds, and row truncation.
Diagram
sequenceDiagram
    participant U as User
    participant A as Argo CD view
    participant C as Context switch
    participant R as Remote resource view

    U->>A: Enter on managed resource
    A->>C: Switch to resolved destination
    C-->>R: Open kind scoped by metadata.name
    U->>R: Esc at root
    R->>C: Switch to original context
    C-->>A: Reopen original Argo CD view
Loading

Reviews (3) · Last reviewed commit: "feat: jump from the Argo CD view into a ..."

Comment thread src/app/argocd.rs
Comment thread src/app/argocd.rs
Comment thread src/app/lifecycle.rs Outdated
@ShmuelOps
ShmuelOps force-pushed the feat/argocd-remote-jump-1 branch from fcfc129 to cf1e2b2 Compare September 17, 2026 11:17
@ShmuelOps

Copy link
Copy Markdown
Contributor Author

Addressed the three review findings in cf1e2b2 (amended into the single commit):

  • Summary row. managed_row_ordinal now returns None past MAX_LISTED, so the "… and N more" line carries no and on it reports where the objects live instead of opening the first hidden resource. Test: argocd_view_summary_row_is_not_a_jump (51 resources, remote destination).
  • Current context by name. classify_destination takes the connected context and maps a resolved context equal to it — by name or by server — to Destination::Current, so rows get ordinary local targets and opens the object here rather than arming a switch that never lands. Tests: two new cases in argocd_destination_classification, plus argocd_destination_resolving_to_the_current_context_is_local through handle_key.
  • Failed switch back. On a failed ContextSwitched the pending return is handed back to argocd_return instead of dropped, since the remote table is still on screen; esc can retry. Test: argocd_remote_jump_failed_return_keeps_the_way_back.

fmt / clippy -D warnings / cargo test --locked (1708) pass.

Comment thread src/app/argocd.rs Outdated
…back

`⏎` on a managed resource of an Application that deploys to another
cluster only reported where the object lives and told the user to `:ctx`
there by hand, then find it again — and the same in reverse to come back.
Since nklmilojevic#570 a remote destination resolves to a kubeconfig context, so the
jump can be made for them.

Pressing `⏎` on such a row switches to the resolved context and, once the
connection lands, opens the object as a root view scoped to its name. The
kind is resolved against the destination cluster at that point, since the
hub may not know the CRD; a kind the destination does not know either
falls back to pods with a warning. The deferred target lives in its own
slot next to the pending query/bookmark/workspace and follows the same
one-at-a-time rules. An unresolved destination still reports where the
objects are, and a heading or source line still has nothing to open.

The jump records where it came from — the hub context and the object the
view was opened for — while the view it opened is on screen. `esc` at that
view's root switches back and reopens the Argo CD view on the same object,
with the table underneath set to that object's kind. `Tab` through the
default kinds keeps the way back (still browsing where the jump landed); a
`:resource` query, bookmark or workspace drops it.

Rows that jump carry the `→` marker: `draw_findings` takes the jump
predicate from the view instead of reading the finding's target, and the
Argo CD view marks a managed-resource row whenever its destination
resolved to a context. Explain and GitOps keep the target-based rule.
@ShmuelOps
ShmuelOps force-pushed the feat/argocd-remote-jump-1 branch from cf1e2b2 to d9048fa Compare September 17, 2026 11:48
@ShmuelOps

Copy link
Copy Markdown
Contributor Author

Follow-up in d9048fa for the locality finding: a resolved context now counts as local only when its kubeconfig server equals the connected cluster_url (normalized) — never by context name. ContextIndex gained server_by_context for that (every admitted context, no alias collapse), and classify_destination takes a server_for_context lookup. The residual case — the connected context's name now pointing at another server — stays Context, and says "kubeconfig context X no longer points at the connected cluster; reconnect with :ctx X" instead of arming a no-op switch. Covered in argocd_destination_classification (name→same server, name→other server, server→same server) and in argocd_destination_resolving_to_the_current_context_is_local through handle_key. 1708 tests pass.

Comment thread src/app/argocd.rs
Comment on lines +309 to +313
if context == self.cluster.context && self.cluster.connected {
self.flash_warn(&format!(
"kubeconfig context {context} no longer points at the connected cluster; reconnect with :ctx {context}"
));
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Reconnect Advice Cannot Work

When kubeconfig remaps the active context name to another server, this branch tells the user to reconnect with :ctx {context}. However, accepting that context calls switch_context, which immediately returns when the requested name matches the connected context. The suggested recovery therefore cannot reconnect to the remapped cluster, leaving the remote managed resource inaccessible until the application is restarted or otherwise disconnected. Provide an in-session path that forces reconnection instead of recommending an operation that is guaranteed to do nothing.

Comment thread src/app/argocd.rs
self.argocd_items
.get(index)
.is_some_and(|f| f.target.is_some())
|| (matches!(self.argocd_destination, Destination::Context(_))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty resource list still marks none reported with an arrow

Comment thread src/app/argocd.rs
// be a no-op, so say what happened instead of dropping the jump.
if context == self.cluster.context && self.cluster.connected {
self.flash_warn(&format!(
"kubeconfig context {context} no longer points at the connected cluster; reconnect with :ctx {context}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch_context early returns, so this ctx advice does nothing

Comment thread src/app/argocd.rs
pub(super) struct ArgocdReturn {
pub context: String,
pub source: DynamicObject,
pub kind: crate::k8s::Kind,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

esc drops the row you left, managed_row_at already exists

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested live: left row 45, esc returns to row 0

Comment thread src/ui.rs
area: Rect,
title: String,
findings: &[crate::explain::Finding],
jumps: &dyn Fn(usize, &crate::explain::Finding) -> bool,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arrow marker is item 5, outside the approved scope

Comment thread src/ui.rs
// The expansion is only discoverable from the title, the way the adjacent
// view advertises the same key.
let title = format!(" {} (c discover children) ", app.argocd_title);
let jumps: Vec<bool> = (0..app.argocd_items.len())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no testbackend test covers this arrow rewiring at all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverting the arrow in draw_argocd still passes 1708 tests

Comment thread src/app/argocd.rs
/// The landing half of [`Self::return_to_argocd`]: the table underneath
/// is the kind the view was opened from, so `esc` out of the view lands
/// somewhere sensible, and the view itself re-reads its object.
pub(super) fn reopen_argocd(&mut self, back: ArgocdReturn) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reopen_argocd should restore the managed row, not row zero

@mesutoezdil

Copy link
Copy Markdown
Contributor

body says three commits and 1705 tests, both stale

@mesutoezdil

Copy link
Copy Markdown
Contributor

same commit is also open at ShmuelOps#1

@mesutoezdil

Copy link
Copy Markdown
Contributor

live service-east to apps-dev-east: jump works, return loses place

@mesutoezdil mesutoezdil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two bugs, one unfinished round trip, one unapproved item.

none reported rows advertise a jump they cannot make.
the drifted kubeconfig flash advises a ctx switch that early returns.
esc comes back to row zero, verified live at 45 rows deep.
the arrow marker is item 5, and reverting it still passes every test.

nr1 and nr2 otherwise work on a real hub and spoke.

@nklmilojevic

Copy link
Copy Markdown
Owner

I'm also not a fan of that many comments in the code. Which model are you using? Seems that it was low quality output from the get go with so many errors that greptile found from the start.

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.

3 participants