Skip to content

Commit 88f1fc8

Browse files
markturanskyAmbient Code Botclaude
authored
fix(control-plane): iterate projects to refresh running session tokens (#1206)
## Summary - `refreshAllRunningTokens` called `factory.ForProject(ctx, "")` which the SDK rejects with `"project is required"` - The refresh loop was silently failing every 10 minutes, leaving runner pod BOT_TOKEN files stale - BOT_TOKEN expiry caused `UNAUTHENTICATED` errors on the gRPC stream — runner unable to push session messages - Fix: list all projects first (using a sentinel project client for the `/projects` endpoint which ignores the project header), then list running sessions per project and refresh each token ## Test plan - [ ] Deploy updated control-plane - [ ] Start a session, wait 10+ minutes - [ ] Verify control-plane logs show token refresh success (no "project is required" warn) - [ ] Verify runner pod continues streaming without UNAUTHENTICATED errors after 15 minutes 🤖 Generated with [Claude Code](https://claude.ai/code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Token refresh operations now reliably support multi-project environments with enhanced error handling that prevents single-project failures from disrupting the entire refresh process. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Ambient Code Bot <bot@ambient-code.local> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 94b0433 commit 88f1fc8

1 file changed

Lines changed: 34 additions & 16 deletions

File tree

components/ambient-control-plane/internal/reconciler/kube_reconciler.go

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -918,29 +918,47 @@ func (r *SimpleKubeReconciler) StartTokenRefreshLoop(ctx context.Context) {
918918
}
919919

920920
func (r *SimpleKubeReconciler) refreshAllRunningTokens(ctx context.Context) {
921-
sdk, err := r.factory.ForProject(ctx, "")
922-
if err != nil {
923-
r.logger.Warn().Err(err).Msg("token refresh loop: failed to get SDK client")
924-
return
925-
}
926-
927-
opts := &types.ListOptions{Page: 1, Size: 100, Search: "phase = 'Running'"}
921+
projectOpts := &types.ListOptions{Page: 1, Size: 100}
928922
for {
929-
list, err := sdk.Sessions().List(ctx, opts)
923+
projectSDK, err := r.factory.ForProject(ctx, "_")
930924
if err != nil {
931-
r.logger.Warn().Err(err).Int("page", opts.Page).Msg("token refresh loop: failed to list running sessions")
925+
r.logger.Warn().Err(err).Msg("token refresh loop: failed to get SDK client")
932926
return
933927
}
934-
for i := range list.Items {
935-
session := list.Items[i]
936-
namespace := r.namespaceForSession(session)
937-
if err := r.refreshRunnerToken(ctx, namespace, session.ID); err != nil {
938-
r.logger.Warn().Err(err).Str("session_id", session.ID).Str("namespace", namespace).Msg("token refresh loop: failed to refresh token")
928+
projectList, err := projectSDK.Projects().List(ctx, projectOpts)
929+
if err != nil {
930+
r.logger.Warn().Err(err).Int("page", projectOpts.Page).Msg("token refresh loop: failed to list projects")
931+
return
932+
}
933+
for _, project := range projectList.Items {
934+
sdk, err := r.factory.ForProject(ctx, project.ID)
935+
if err != nil {
936+
r.logger.Warn().Err(err).Str("project_id", project.ID).Msg("token refresh loop: failed to get SDK client for project")
937+
continue
938+
}
939+
sessionOpts := &types.ListOptions{Page: 1, Size: 100, Search: "phase = 'Running'"}
940+
for {
941+
list, err := sdk.Sessions().List(ctx, sessionOpts)
942+
if err != nil {
943+
r.logger.Warn().Err(err).Str("project_id", project.ID).Int("page", sessionOpts.Page).Msg("token refresh loop: failed to list running sessions")
944+
break
945+
}
946+
for i := range list.Items {
947+
session := list.Items[i]
948+
namespace := r.namespaceForSession(session)
949+
if err := r.refreshRunnerToken(ctx, namespace, session.ID); err != nil {
950+
r.logger.Warn().Err(err).Str("session_id", session.ID).Str("namespace", namespace).Msg("token refresh loop: failed to refresh token")
951+
}
952+
}
953+
if len(list.Items) == 0 || list.Total <= sessionOpts.Page*sessionOpts.Size {
954+
break
955+
}
956+
sessionOpts.Page++
939957
}
940958
}
941-
if len(list.Items) == 0 || list.Total <= opts.Page*opts.Size {
959+
if len(projectList.Items) == 0 || projectList.Total <= projectOpts.Page*projectOpts.Size {
942960
break
943961
}
944-
opts.Page++
962+
projectOpts.Page++
945963
}
946964
}

0 commit comments

Comments
 (0)