Skip to content

fix(node): clarify upsert guard message for pool-sourced HFID attributes#1106

Merged
minitriga merged 1 commit into
stablefrom
fix/numberpool-hfid-upsert-message
Jun 26, 2026
Merged

fix(node): clarify upsert guard message for pool-sourced HFID attributes#1106
minitriga merged 1 commit into
stablefrom
fix/numberpool-hfid-upsert-message

Conversation

@ogenstad

@ogenstad ogenstad commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

The ValidationError raised by _validate_upsert claimed the upsert "cannot resolve the HFID without a concrete value", implying a backend crash. Since #312 the SDK no longer sends the HFID in the upsert payload, so that premise is stale. The real problem is different: a CoreNumberPool assigns a new value on every creation, so a pool-sourced HFID attribute is never stable, an upsert can never match an existing node by it, and every run would silently create a duplicate.

Reword the error message and docstring to describe this, and point to the idempotent alternatives (look the node up by a stable field and reuse it, or set an explicit id). Update the resource manager guide to match and replace the misleading "two-step pattern" with the lookup-and-reuse pattern that the demo generators actually use.

Add an integration test characterising the real backend behaviour (a no-id upsert creates and allocates the pool value; a re-run duplicates) and extend the unit test to cover the new message.

Refs #339, #396

Why

The client-side guard added in #1014 (InfrahubNode._validate_upsert) raises a ValidationError when you call save(allow_upsert=True) on a node whose human-friendly identifier (HFID) includes a CoreNumberPool-sourced attribute. Its message says the upsert "cannot resolve the HFID without a concrete value", which implies a backend/HFID-resolution failure. That premise is stale: since #312 the SDK no longer sends the HFID in the upsert payload, so there is no such crash.

This surfaced while reviewing opsmill/infrahub-demo-service-catalog#114, where the VLAN generator hit this guard. The real reason the operation is a problem is different and worth stating correctly: a CoreNumberPool allocates a new value on every creation, so a pool-sourced HFID attribute is never stable. An upsert can therefore never match an existing node and would silently create a duplicate on each run.

Goal: make the error message and docs explain the actual problem and point to the patterns that work.

Non-goals: this does NOT change the guard's behavior (it still blocks, which is correct - the alternative is silent duplicate creation) and does NOT add idempotent number-pool allocation (that's #396).

What changed

Behavioral changes:

  • None. The guard still raises for the same inputs; only the message text changes.

Message/docs:

  • Reworded the ValidationError message and _validate_upsert docstring to describe the non-idempotency/silent-duplication problem and the fix: look the node up by a stable attribute or relationship and reuse it, or set an explicit id.
  • Updated the resource manager guide to match, and replaced the misleading "two-step pattern" alternative with the lookup-and-reuse pattern the demo generators actually use.

Tests:

  • Added an integration test characterising the real backend behaviour: a no-id upsert of a pool-HFID node creates the node and allocates the value, and a re-run produces a duplicate (the feature: Add identifier support for number pools in SDK #396 limitation).
  • Extended the unit test to assert the new message text.

What stayed the same: guard logic, public API, and when the error fires are all unchanged.


Summary by cubic

Clarified the upsert guard for nodes whose HFID includes a CoreNumberPool value: pool values change on each creation, so the HFID is unstable and upserts would duplicate; the SDK now raises a clearer error with guidance. Updated docs to promote the lookup-and-reuse pattern and added tests to characterize backend behavior.

  • Bug Fixes
    • Reworded ValidationError and docstring in InfrahubNode._validate_upsert to explain non-idempotent duplicates and suggest alternatives (lookup by a stable field/relationship or set an explicit id before save(allow_upsert=True)).
    • Updated resource manager guide to replace the “two-step pattern” with the lookup-and-reuse approach and clarified the CoreNumberPool HFID limitation.
    • Added an integration test to show that a no-id upsert creates and allocates the pool value, and re-runs may duplicate; extended unit tests to validate the new message.

Written for commit 853e01d. Summary will update on new commits.

Review in cubic

The ValidationError raised by _validate_upsert claimed the upsert "cannot
resolve the HFID without a concrete value", implying a backend crash. Since
#312 the SDK no longer sends the HFID in the upsert payload, so that premise
is stale. The real problem is different: a CoreNumberPool assigns a new value
on every creation, so a pool-sourced HFID attribute is never stable, an upsert
can never match an existing node by it, and every run would silently create a
duplicate.

Reword the error message and docstring to describe this, and point to the
idempotent alternatives (look the node up by a stable field and reuse it, or
set an explicit id). Update the resource manager guide to match and replace
the misleading "two-step pattern" with the lookup-and-reuse pattern that the
demo generators actually use.

Add an integration test characterising the real backend behaviour (a no-id
upsert creates and allocates the pool value; a re-run duplicates) and extend
the unit test to cover the new message.

Refs #339, #396
@github-actions github-actions Bot added the type/documentation Improvements or additions to documentation label Jun 26, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 853e01d
Status: ✅  Deploy successful!
Preview URL: https://dbcf25f8.infrahub-sdk-python.pages.dev
Branch Preview URL: https://fix-numberpool-hfid-upsert-m.infrahub-sdk-python.pages.dev

View logs

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@           Coverage Diff           @@
##           stable    #1106   +/-   ##
=======================================
  Coverage   82.15%   82.16%           
=======================================
  Files         138      138           
  Lines       11896    11896           
  Branches     1784     1784           
=======================================
+ Hits         9773     9774    +1     
+ Misses       1575     1572    -3     
- Partials      548      550    +2     
Flag Coverage Δ
integration-tests 41.18% <ø> (+0.05%) ⬆️
python-3.10 55.25% <ø> (-0.02%) ⬇️
python-3.11 55.27% <ø> (+0.01%) ⬆️
python-3.12 55.25% <ø> (ø)
python-3.13 55.25% <ø> (-0.02%) ⬇️
python-3.14 55.26% <ø> (ø)
python-filler-3.12 22.74% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/node/node.py 87.57% <ø> (+0.09%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 5 files

Re-trigger cubic

@ogenstad ogenstad marked this pull request as ready for review June 26, 2026 14:38
@ogenstad ogenstad requested a review from a team as a code owner June 26, 2026 14:38
@minitriga minitriga merged commit 7f37905 into stable Jun 26, 2026
21 checks passed
@minitriga minitriga deleted the fix/numberpool-hfid-upsert-message branch June 26, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants