Documentation
¶
Overview ¶
Package tunnel provides stall detection for kubectl port-forward tunnels.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Watch ¶
func Watch(ctx context.Context, httpPort, httpsPort int, interval, probeTimeout time.Duration, strikes int, id func() any, kill func(id any), onEvent func(string))
Watch probes a kubectl port-forward tunnel and calls kill when the tunnel is wedged: the local port still accepts TCP connections (kubectl is alive) but forwarded requests never complete. That failure mode is invisible to exit-based supervision — kubectl only exits on hard upstream errors, not on a stalled apiserver stream — and it fails every request until the tunnel is replaced (observed in CI on MR !1306: HAProxy healthy and serving on both pods, zero requests arriving through the tunnel for the whole 15s budget).
httpPort is probed with a plain HTTP request; ANY status code is a healthy tunnel — HAProxy answering 404 still proves end-to-end forwarding. When httpPort is 0, httpsPort is probed with an insecure TLS handshake instead. A refused connection is NOT a strike: it means the process is dead or restarting, which exit-based supervision already handles. After `strikes` consecutive probe timeouts kill is invoked once and the count resets, so a replacement tunnel starts with a fresh budget.
Strikes are scoped to one process: id() identifies the process currently serving the tunnel, an identity change resets the count, and the identity the strikes were counted against is passed to kill so the caller can refuse to kill a newer process — the supervisor may swap tunnels at any moment.
Watch returns when ctx is done. onEvent receives one line per kill for the caller to log.
Types ¶
type RecoveryConfig ¶
type RecoveryConfig struct {
MinBackoff time.Duration // pause after the first failed attempt
MaxBackoff time.Duration // cap on the exponential backoff
Budget time.Duration // give up once this much has elapsed with no success
}
RecoveryConfig bounds how Reestablish retries a failed tunnel handshake.
type RecoveryResult ¶
type RecoveryResult int
RecoveryResult reports how Reestablish stopped.
const ( // RecoveryRecovered means establish finally returned nil. RecoveryRecovered RecoveryResult = iota // RecoveryCtxDone means ctx ended before a success. RecoveryCtxDone // RecoveryBudgetExceeded means Budget elapsed with every attempt failing. RecoveryBudgetExceeded )
func Reestablish ¶
func Reestablish(ctx context.Context, establish func(context.Context) error, cfg RecoveryConfig, onEvent func(string)) RecoveryResult
Reestablish retries within Budget; attempt contexts end on return and must not own the recovered process.