fix(cli): run the platform-credential import whatever hook cobra picks - #4175
Merged
Merged
Conversation
The import hung on the root's PersistentPreRun, and cobra runs only the nearest one: any subtree declaring a hook of its own removed the identity from every verb beneath it. Eighteen subtrees had one that did nothing but set SilenceUsage, so in a fresh container `market list`, `settings`, `router`, `knowledge` and all of `cluster` reported that no profile was configured while the credential sat unread on its mount. `profile list`, one of the few trees without a hook, repaired the container for whatever ran after it. Wrap the import around every declared hook instead of placing it in one, and set SilenceUsage on the root, which covers the whole tree and replaces the eighteen hooks that caused this. The nfs backend-version gate keeps its hook and now runs with an identity available. The existing importer tests all call the importer directly, so none of them could see this. The new end-to-end cases drive the real tree the way a container does and assert on config.json. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
pengpeng
added a commit
to beclab/lares
that referenced
this pull request
Sep 20, 2026
…#30) olares-cli imported the mounted credential only from a hook that most subtrees shadowed, so a conversation opening with a market, cluster, settings, router or knowledge question was told no profile was configured and only recovered once some other command had run. 1.12.7-cli.10 runs the import whatever hook cobra picks (beclab/Olares#4175). Dockerfile.base changed, so image_base_tag moves with it. Co-authored-by: Cursor <cursoragent@cursor.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
In a container that app-service gave a credential to, the first command fails unless it happens to be one of a handful of verbs:
78ms does not fit a token exchange, so the failing run never attempted the import;
profile listdid it, and everything after it worked.Why
credential.ImportManagedCredentialhung on the root'sPersistentPreRun, and cobra runs only the nearest persistent hook it finds walking up from the command that ran (command.go,breakunlessEnableTraverseRunHooks). Nineteen subtrees declared a hook of their own, so none of them ever reached the root's —market,settings,router,knowledge,download,chart,skills,preinstall,files nfs, andclusterwith its nine children.profiledeclares none, which is why it was the one command that repaired the container.Eighteen of those nineteen hooks existed only to set
SilenceUsage, because setting the field on a group does nothing: cobra consults the root and the command that actually ran, never anything in between. A cosmetic need borrowed the one mechanism that also carried authentication, and that is where the bug came from.The placement predates this;
#4174is what made it visible, because before it every command failed for a different reason.The fix
Wrap, don't place.
wireManagedIdentitywalks the tree and wraps the import around every command that declares a hook, bothPersistentPreRunandPersistentPreRunE. A command without one runs an ancestor's, and the root declares one, so every path ends at something wrapped. It runs beforeskipPreRunsForGroupHelpso<group> helpstill skips everything, and before each wrapped body so thefiles nfsversion gate now has an identity when it checks — a latent bug of its own.viper.BindPFlagsstays in the root's body; giving those subtrees viper bindings is a different blast radius.Remove the cause.
SilenceUsage: trueon the root covers the whole tree, so the eighteen decorative hooks are deleted. The nineteenth (files nfs) does real work and stays.Behavior changes
profile,dashboard,search,doctor,filesandversionno longer print full usage after an error, matching the other eighteen trees.chart,skills,preinstall), costing one exchange per invocation. It stays a no-op on host installs with no credential mount.Left alone deliberately, against an earlier draft of this change: the
SilenceUsagefields on group commands and leaves are not redundant. A group is the command that ran when it refuses an unknown verb, and a leaf is the case cobra checks. Removing them would change behavior, not just noise.Tests
All fifteen existing importer tests call
managedImporter.rundirectly, so none of them could tell whether cobra still called it. That is the layer this adds.cmd/ctl/managed_identity_test.gostands up a credential mount and a cache directory undert.TempDir(), points the grant exchange at a local server that refuses it — which keeps the test off DNS and off the system keychain, while still creating the profile entry — then runs a real verb and readsconfig.jsonback. Only the importer ever marks a profile managed; resolving one never writes the file.Four paths, one container each:
market list(no hook below the root),files nfs history list(its own hook),profile list(the one that used to work),cluster pod list(a group two levels down). Onmainthe first, second and fourth fail with the container's exact message andprofile listpasses — the session above, reproduced.A second test asserts the root's
SilenceUsageand that the only commands declaring hooks are the root,files nfs, andbackups(which brings its own from backups-sdk). Adding a hook is fine — the walker covers it — but the failure points at the table above so a new subtree gets a case rather than silently going unchecked.Also verified in a container with the cross-built linux binary, first command, nothing else run before it:
market listconfig.jsonmainno Olares profile is configured: …mounted but could not be loaded/api/refresh: … no such host(the test credential is fake)go vet ./cmd/...,go test ./cmd/... ./pkg/credential/... ./pkg/cliconfig/..., andCGO_ENABLED=0 GOOS=linux go build ./cmd/are green.Made with Cursor