Skip to content

Make admin tool bootstrap idempotent for already-bootstrapped realms#4996

Merged
dimas-b merged 2 commits into
apache:mainfrom
sepandr:bootstrap-already-bootstrapped-idempotent
Jul 10, 2026
Merged

Make admin tool bootstrap idempotent for already-bootstrapped realms#4996
dimas-b merged 2 commits into
apache:mainfrom
sepandr:bootstrap-already-bootstrapped-idempotent

Conversation

@sepandr

@sepandr sepandr commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Running the admin tool's bootstrap against a realm that is already bootstrapped currently throws IllegalArgumentException ("It appears this metastore manager has already been bootstrapped…") and exits with the generic EXIT_CODE_BOOTSTRAP_ERROR (3) — the same code as every real failure. That makes automated deployments (Kubernetes Jobs, ArgoCD hook Jobs that run bootstrap on every deploy) fail on any redeploy, with no reliable way to distinguish the benign case short of matching the error text, and Kubernetes offers no "treat exit N as success" escape hatch. See #4995 for full context.

This change makes re-bootstrap a graceful no-op:

  • AuthBootstrapUtil.createPolarisPrincipalForRealm returns a PrincipalSecretsResult with ReturnStatus.ENTITY_ALREADY_EXISTS instead of throwing when the root principal already exists (same for the duplicated check in LocalPolarisMetaStoreManagerFactory).
  • PolarisMetaStoreManager.bootstrapPolarisService propagates that result (javadoc updated).
  • BootstrapCommand prints Realm '<realm>' is already bootstrapped; skipping. for such realms and keeps exit code 0; all other failures still exit 3. --print-credentials never prints anything for skipped realms — existing credentials are never returned or altered, and realms in the same invocation that are not yet bootstrapped are still bootstrapped normally.

Testing: new testBootstrapAgainIsNoOp in BasePolarisMetaStoreManagerTest (runs for both TreeMap metastore variants) asserts the second bootstrap reports alreadyExists() and the realm stays fully intact; existing bootstrap/purge CLI tests pass unchanged (:polaris-core:test, :polaris-admin:test in-memory variants run locally; an admin-CLI-level double-bootstrap test isn't possible yet because consecutive launches don't reuse the dev-services container — see the existing TODO in RelationalJdbcBootstrapCommandTest). Also verified behaviorally against a live 1.5.0 deployment (relational-jdbc on PostgreSQL 16) where re-running bootstrap on an existing realm currently fails.

AI assistance disclosure: this PR was developed with the assistance of Claude (Anthropic's coding assistant), per the Guidelines for AI-assisted Contributions. I have reviewed, tested, and understand all of the changes, and assume full authorship of and responsibility for the contribution.

Checklist

dimas-b
dimas-b previously approved these changes Jul 7, 2026

@dimas-b dimas-b left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution, @sepandr ! Very reasonable change.

Given that is affects bootstrap behaviour, let's keep it in review for a few more days for other people to have a chance to comment.

@github-project-automation github-project-automation Bot moved this from PRs In Progress to Ready to merge in Basic Kanban Board Jul 7, 2026
@dimas-b

dimas-b commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

FYI: @obelix74 , @tokoko , @cccs-cat001

@sepandr

sepandr commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for your contribution, @sepandr ! Very reasonable change.

Given that is affects bootstrap behaviour, let's keep it in review for a few more days for other people to have a chance to comment.

@dimas-b thanks for your review, sounds good!

nandorKollar
nandorKollar previously approved these changes Jul 8, 2026

@cccs-cat001 cccs-cat001 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wanting this for months now! Great change :)

@vigneshio vigneshio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceProducers assumes all bootstrap results have secrets (getPrincipalSecrets()), but with this change some results will be alreadyExists. Worth handling here or quick follow-up? WDYT ?? @dimas-b

@sepandr
sepandr dismissed stale reviews from nandorKollar and dimas-b via d316f18 July 8, 2026 13:43
@dimas-b

dimas-b commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

ServiceProducers assumes all bootstrap results have secrets (getPrincipalSecrets()), but with this change some results will be alreadyExists. Worth handling here or quick follow-up?

I'd say the code should not assume that 😅 Only the first bootstrap should emit auto-generated credentials. If that's what you mean by follow-up then, let's do that :)

My personal preference is to avoid generating user-owned secrets in Polaris completely. Right now the admin use has both options: 1) provide a secret or 2) let Polaris generate it.

Ideally, the schema setup should be idempotent. The "root" user set up should be separate (e.g. via Terraform). With external IdP the root user does not even have to exist, but that requires more work to follow #4356

All in all, +1 to follow-up improvements, but I'm afraid it's a long road 😅

@dimas-b

dimas-b commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@sepandr : Some of the commits mention Claude as a formal co-author. It is fine to use AI to make contributions, but a human has to assume authorship, I think.

Cf. #4106 (comment)

Cf. https://polaris.apache.org/community/contributing-guidelines/#guidelines-for-ai-assisted-contributions

sepandr added 2 commits July 9, 2026 16:46
Bootstrapping a realm that already has a root principal used to throw
IllegalArgumentException, which BootstrapCommand mapped to the generic
EXIT_CODE_BOOTSTRAP_ERROR. Automated deployments (e.g. Kubernetes Jobs
or ArgoCD hooks) that run bootstrap on every deploy therefore failed on
any redeploy, and callers could not distinguish the benign case from
real failures except by matching the error-message text.

AuthBootstrapUtil.createPolarisPrincipalForRealm now returns a
PrincipalSecretsResult with ENTITY_ALREADY_EXISTS instead of throwing,
PolarisMetaStoreManager.bootstrapPolarisService propagates that result,
and BootstrapCommand reports "Realm 'x' is already bootstrapped;
skipping." while keeping exit code 0. Existing credentials are never
returned or altered; realms that are not yet bootstrapped are still
bootstrapped normally.

Fixes apache#4995
…tion message

- testBootstrapAgainIsNoOp now asserts ReturnStatus.ENTITY_ALREADY_EXISTS
  directly instead of isSuccess() + alreadyExists()
- BootstrapCommand reports 'Bootstrap completed (N realm(s) already
  bootstrapped).' when realms were skipped, keeping 'Bootstrap completed
  successfully.' for full bootstraps
@sepandr
sepandr force-pushed the bootstrap-already-bootstrapped-idempotent branch from d316f18 to c60a606 Compare July 9, 2026 23:46
@sepandr

sepandr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the pointer @dimas-b — you're right. I've rewritten the branch to drop the Co-Authored-By trailer (no AI tool references remain in the commit messages; the code is unchanged) and added an AI-assistance disclosure to the PR description instead, per the contributing guidelines.

@dimas-b dimas-b left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @sepandr !

Merging as soon as CI is green.

@dimas-b
dimas-b enabled auto-merge (squash) July 9, 2026 23:54

@flyrain flyrain Jul 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may accidentally make this function not suitable for any callers other than bootstrapping. I understand bootstrapping is the only use case now, should we change the method name to make it explicitly only for bootstrapping?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class name is specific to bootstrapping. Renaming to avoid confusion is also fine. @flyrain : Would you like to propose a PR for that?

@dimas-b
dimas-b merged commit cfcd59d into apache:main Jul 10, 2026
25 checks passed
@github-project-automation github-project-automation Bot moved this from Ready to merge to Done in Basic Kanban Board Jul 10, 2026
@flyrain

flyrain commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Can we wait until all comments are resolved?

@dimas-b

dimas-b commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Can we wait until all comments are resolved?

@flyrain : I enabled auto-merge (as noted above) based on the previous approvals and the 2 day review period. I believe you could have disabled the auto-merge.

@flyrain

flyrain commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Can we wait until all comments are resolved?

@flyrain : I enabled auto-merge (as noted above) based on the previous approvals and the 2 day review period. I believe you could have disabled the auto-merge.

Got it. I guess auto merge will naturally ignore new comments. I'd suggest using it with caution.

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.

Admin tool bootstrap command is not idempotent: fails on already-bootstrapped realms

7 participants