Skip to content

feat(seinode): publish per-node endpoint URLs in status#418

Merged
bdchatham merged 2 commits into
mainfrom
feat/seinode-endpoint-status
Jun 18, 2026
Merged

feat(seinode): publish per-node endpoint URLs in status#418
bdchatham merged 2 commits into
mainfrom
feat/seinode-endpoint-status

Conversation

@bdchatham

Copy link
Copy Markdown
Collaborator

What

Adds SeiNode.status.endpoint (NodeEndpointStatus) so a follower node's in-cluster URLs — evmJsonRpc, evmWs, tendermintRpc, tendermintRest — are discoverable by external orchestration. Populated only for EVM-serving modes (fullNode/archive); validator/replayer leave the field absent.

Why

The migration off SeiNodeDeployment needs an EVM JSON-RPC load target for the nightly chaos harness. That target must be a follower node — genesis validators run ModeValidator, which disables EVM HTTP/WS — but SeiNodeStatus had no endpoint fields, so a standalone follower surfaced nothing to read.

This change makes the controller expose the endpoint; it deliberately does not create load balancers or gate status on a deep health probe. The controller's job is discoverability — readiness probing and load-balancing decisions belong to the consumer (seictl / platform CICD), which picks the strategy that fits its case.

Design

  • Status-only, additive. New optional pointer field + type. No spec change, no CRD version bump, backward-compatible.
  • No new Service, no RBAC change. URLs are pure derivation from the headless Service the SeiNode reconcile already applies (<name>.<ns>.svc + seiconfig.Port*). Mirrors the existing seinetwork endpoint composition.
  • Mode-gated on the spec sub-spec (FullNode/Archive), not noderesource.NodeMode — which collapses replayer -> ModeFull and would wrongly surface endpoints for an ephemeral replayer (regression-guarded in tests).
  • Readiness is a consumer concern. .status.endpoint is a discoverability signal, not a serve-readiness guarantee (PhaseRunning is set by a no-op MarkReadyHandler); consumers probe before driving load.

Tests

servesEVM truth table; exact-URL asserts for fullNode/archive; nil for validator/replayer; reconcile-integration (fullNode->Running sets endpoint + Service exposes :8545; validator->nil; idempotent/no-churn across reconciles). All pass; node package 88.7% coverage.

Note: make test exits non-zero in some local toolchain setups due to a gvm go1.26-shim / go1.25.6-pkgset -coverprofile stdlib-recompile mismatch — environmental, not a test failure (every package prints ok; verified clean without -coverprofile).

Provenance

Design + cross-review captured in the migration workspace (LLD WS-A0-controller-lld.md; xreview ledger RESOLVED — kubernetes-specialist + sei-network-specialist + platform-engineer + idiomatic-reviewer). Unblocks the seictl network/node split (WS-A) and the platform nightly migration (WS-C).

🤖 Generated with Claude Code

Add SeiNode.status.endpoint (NodeEndpointStatus) so a follower node's
in-cluster EVM/Tendermint URLs are discoverable by external orchestration.
Gated on EVM-serving mode (fullNode/archive); validator/replayer surface
nothing. Pure status derivation from the existing headless Service — no new
Service, no RBAC change.

The controller publishes the discoverable address only; readiness probing and
load-balancing decisions belong to the consumer, not the controller.

Unblocks the seictl/platform migration off SeiNodeDeployment: the follower
RPC fleet (not the genesis validators, which don't serve EVM) becomes the
load target.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cursor

cursor Bot commented Jun 18, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Additive status-only CRD change with no new cluster resources or RBAC; main caveat is consumers treating URLs as ready without probing.

Overview
Adds optional SeiNode.status.endpoint (NodeEndpointStatus) so orchestration can read in-cluster URLs for standalone follower nodes without inventing DNS themselves.

When phase is Running, the node reconciler sets endpoint URLs derived from the existing headless Service (<name>.<namespace>.svc) and seiconfig ports: EVM JSON-RPC/WS plus Tendermint RPC and REST. Full node and archive modes get the full bundle; validator and replayer leave the field absent. Gating uses spec.fullNode / spec.archive, not internal mode enums, so replayers are not mis-advertised as RPC targets.

Endpoints are documented as discoverability only (not listener readiness). The controller does not clear endpoint on brief non-Running phases, to avoid status flapping. CRD/manifests and deepcopy are updated; unit and reconcile tests cover URL shape, mode nil cases, and idempotency.

Reviewed by Cursor Bugbot for commit b3e9e06. Bugbot is set up for automated code reviews on this repo. Configure here.

CRD descriptions are generated from the Go doc comments; regenerate so
verify-generated matches the source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bdchatham bdchatham merged commit e0bf719 into main Jun 18, 2026
5 checks passed
@bdchatham bdchatham deleted the feat/seinode-endpoint-status branch June 18, 2026 19:26
bdchatham added a commit that referenced this pull request Jun 20, 2026
…de RBAC (#420)

* feat(seitask): WS-C — rpc scenario templates → SeiNode + provision-node RBAC

- runner/rbac.yaml: grant seitask-runner `seinodes` create (provision-node's
  first act is c.Create(SeiNode); without it every rpc-fleet step 403s) +
  seinodes/status get (forward-compat, matches the /status pattern).
- scenarios/{load-test,release-test}/rpc.yaml.tmpl: rewrite from a dead second
  `kind: SeiNetwork` (replicas:2) to a single `kind: SeiNode` fullNode follower;
  name/ns/ownerRef/labels/peers stamped by provision-node at runtime.

Pairs with platform WS-C (chaos workflows → provision-node) and consumes the
merged provision-node (#419) + SeiNode.status.endpoint (#418).

HARD GATE before merge: dry-run the rendered SeiNode template against the
DEPLOYED CRD (`seictl node apply … --dry-run`) — envtest only covers the
repo CRD, not the live one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(seitask): move rpc.yaml.tmpl render-clean guard to provisionnode

The WS-C rewrite of scenarios/{load-test,release-test}/rpc.yaml.tmpl from
kind: SeiNetwork to kind: SeiNode broke provisionsnd's
TestBundledTemplates_RenderClean, which strict-unmarshals every bundled
template as a SeiNetwork (rendered SeiNode has top-level spec.chainId, an
unknown field on SeiNetworkSpec).

- provisionsnd test: drop the rpc.yaml.tmpl case — it only owns the
  SeiNetwork genesis/validator templates now.
- provisionnode test: add TestBundledTemplates_RenderClean covering both
  rpc.yaml.tmpl, asserting they render + strict-unmarshal as a SeiNode
  (spec.chainId set, spec.fullNode present).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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