Build a Bearer-authenticated channel to the gateway. First call per process resolves the sandbox JWT via the three-step lookup (env → file → K8s SA bootstrap exchange) and installs it into the process-wide [`TOKEN_SLOT`]. Subsequent calls reuse the cached slot — the renewal loop keeps the value fresh, so re-running the bootstrap is both unnecessary and (on the K8s SA path) expensive (one apiserve
(endpoint: &str)
| 193 | /// (one apiserver round-trip per call). The renewal loop itself is |
| 194 | /// spawned once per process via [`REFRESH_SPAWNED`]. |
| 195 | async fn connect_channel(endpoint: &str) -> Result<AuthedChannel> { |
| 196 | let channel = build_plain_channel(endpoint).await?; |
| 197 | let (slot, refresh_mode) = token_slot(endpoint, &channel).await?; |
| 198 | let plain_channel = channel.clone(); |
| 199 | let intercepted = InterceptedService::new(channel, AuthInterceptor::new(slot.clone())); |
| 200 | if REFRESH_SPAWNED.set(()).is_ok() { |
| 201 | let RefreshMode::GatewayJwt(source) = refresh_mode; |
| 202 | let refresh_channel = intercepted.clone(); |
| 203 | let endpoint = endpoint.to_string(); |
| 204 | tokio::spawn(async move { |
| 205 | refresh_token_loop(refresh_channel, slot, source, endpoint, plain_channel).await; |
| 206 | }); |
| 207 | } |
| 208 | Ok(intercepted) |
| 209 | } |
| 210 | |
| 211 | async fn token_slot(endpoint: &str, plain_channel: &Channel) -> Result<(TokenSlot, RefreshMode)> { |
| 212 | if let Some(existing) = TOKEN_SLOT.get() { |
no test coverage detected