Skip to content

[wip] OSAC-1610: NetBox Inventory Backend Design - #289

Open
mennyaboush wants to merge 5 commits into
osac-project:mainfrom
mennyaboush:design/OSAC-4347-netbox-inventory-impl
Open

mennyaboush wants to merge 5 commits into
osac-project:mainfrom
mennyaboush:design/OSAC-4347-netbox-inventory-impl

Conversation

@mennyaboush

@mennyaboush mennyaboush commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Design document for NetBox as a pluggable inventory backend for OSAC bare-metal fulfillment.

Design Highlights

  • Inventory Pattern: Follows BCM backend model (in-tree, Metal3 integration required)
  • Allocation Tracking: Custom field osac_instance_id with read-after-write verification
  • Power Management: Inventory client manages Metal3 BareMetalHost lifecycle
  • Credential Security: BMC credentials stored in NetBox, fetched at assignment time
  • Device Filtering: Tag-based pool selection (tag=managed_by:osac) + staged status
  • E2E Testing: Real NetBox container with version compatibility testing
  • Version Compatibility: Open question highlighting NetBox 4.7 breaking changes

Documents

  • Design: enhancements/OSAC-1610-netbox-inventory/design.md
  • Test Plan: enhancements/OSAC-1610-netbox-inventory/testplan.md
  • PRD: OSAC-4346 (merged)

Related

🤖 Generated with Claude Code

Summary

  • Documentation: Added the PRD, design document, clarification log, and test plan.
  • API and controllers: Proposed, but did not implement, NetBoxConfig, NetBoxClient, and Metal3/BareMetalHost lifecycle workflows.
  • Allocation: Defined host discovery, label and status filtering, allocation tracking, assignment, unassignment, idempotency, and crash recovery.
  • Authentication and security: Documented token authentication, TLS, CA secrets, BMC credential retrieval, validation, authorization, and tenant isolation.
  • Deployment and operations: Documented in-tree deployment through Helm values and Enclave Wizard, retries, observability, failure recovery, and support procedures.
  • Tests: Defined 53 unit, integration, and end-to-end scenarios, including Kind-based workflows and real-NetBox testing.
  • CI and tracking: Jira validation passed. OSAC-1610 has no target version, while the target branch expects 5.1.0.

Compatibility

This PR adds documentation only. It does not change executable code, runtime configuration, public APIs, stored data, or controller behavior.

The proposed backend would use NetBox for inventory and allocation tracking. Metal3/BareMetalHost would continue to manage provisioning and power operations. NetBox version compatibility remains unresolved because the design identifies minor-version breaking changes and does not select a supported version range.

Risk classification

risk:ship — The PR changes documentation and test plans only. It does not change production behavior, deployment configuration, public interfaces, or stored data.

The PR is close to risk:show because it specifies a new backend, allocation state, Metal3 integration, authentication, and deployment configuration. It does not qualify because the implementation is not included.

@openshift-ci-robot

openshift-ci-robot commented Sep 14, 2026 •

Copy link
Copy Markdown

@mennyaboush: This pull request references OSAC-1610 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the feature to target the "5.1.0" version, but no target version was set.

Details

In response to this:

Summary

Design document for NetBox as a pluggable inventory backend for OSAC bare-metal fulfillment.

Design Highlights

  • Inventory Pattern: Follows BCM backend model (in-tree, Metal3 integration required)
  • Allocation Tracking: Custom field osac_instance_id with read-after-write verification
  • Power Management: Inventory client manages Metal3 BareMetalHost lifecycle
  • Credential Security: BMC credentials stored in NetBox, fetched at assignment time
  • Device Filtering: Tag-based pool selection (tag=managed_by:osac) + staged status
  • E2E Testing: Real NetBox container with version compatibility testing
  • Version Compatibility: Open question highlighting NetBox 4.7 breaking changes

Documents

  • Design: enhancements/OSAC-1610-netbox-inventory/design.md
  • Test Plan: enhancements/OSAC-1610-netbox-inventory/testplan.md
  • PRD: OSAC-4346 (merged)

Related

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci
openshift-ci Bot requested review from danmanor and eliorerz September 14, 2026 09:13
@github-actions

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

AI EP Review: EP-289

Score: 9/10 | Verdict: PASS
Feature: OSAC-1610

Criterion Score Notes
WHAT (clear need) 2/2 Clear new platform capability (NetBox as inventory backend for BMaaS). All four canonical personas covered with per-persona user stories. Tenant Admin / Tenant User consolidated heading is genuine — capability is identical for both. BMaaS service and relevant cross-cutting dimensions identified.
WHY (justification) 2/2 Concrete justification: names specific pain (data inconsistency, operational burden during host lifecycle changes, misalignment risk) for a concrete scenario (sovereign-cloud operator using NetBox as authoritative source of truth). Ties to real operational cost, not generic need.
User-Facing Focus 1/2 Mostly user-focused but some design leakage. In Scope prescribes 'API-token input rendered into a Helm-created Secret' (implementation mechanism). Assumptions specify internal field names (osac_instance_id, osac_managed), exact status values (staged/active), and tracking mechanics at field-level granularity. These are design decisions, not user-observable requirements — the PRD should describe what the admin configures and observes, not the internal data model.
Right-Sized 2/2 One coherent capability that can't be decomposed — configuration, allocation, deallocation, credential management, and error handling are interdependent. Economical treatment: no restated stories, no extra sections, no padding. One step past the nothing baseline.
Testability 2/2 Every In Scope requirement is verifiable by using the product: configure backend, trigger connectivity/credential errors, provision and deprovision hosts, attempt parallel requests, verify tenant error messages, inspect NetBox for tenant data absence.

Verdict: Strong PRD with clear user-facing need, concrete justification, focused scope, and fully testable requirements; held back from a perfect score only by design leakage in the Assumptions section and one In Scope item that prescribes implementation mechanics.

Feedback: Move the field-level specifics from Assumptions (osac_instance_id, osac_managed, status=staged/active) into the design document — the PRD should say the admin configures pool membership and OSAC tracks allocation state, without prescribing field names or status values. Rewrite the In Scope credential bullet to describe what the admin does ('provides an API token through deployment configuration') rather than how it's stored ('rendered into a Helm-created Secret'). These changes would bring User-Facing Focus to a 2.

Critical (0)

None.

Important (2)

  1. Assumptions section contains design-level detail: specific NetBox custom field names (osac_instance_id, osac_managed), exact status values (staged/active), and the tracking mechanism. These prescribe the implementation and belong in the design document, not the PRD.
  2. In Scope bullet 'API-token input rendered into a Helm-created Secret' prescribes the credential storage mechanism rather than describing the user-observable configuration action.

Suggestions (1)

  1. The assumption about enrolled hosts having 'valid, unique names that can be used unchanged by Metal3' references an internal component (Metal3) — consider rephrasing to describe the requirement from the admin's perspective (e.g., 'names that meet Kubernetes naming constraints').

Structural notes (0)

None.


Review cost

Model: claude-opus-4-6
Cost: $0.5670
Tokens: 1.4k in / 4.8k out
Cache: 84.9k read
Active time: 1m 44s
API calls: 0

@github-actions github-actions Bot added the rfe-creator-auto-reviewed EP was reviewed by AI label Sep 14, 2026
@github-actions

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

AI Design Review: EP-289

Score: 8/8 | Verdict: PASS
Feature: OSAC-1610

Criterion Score Notes
Feasibility 2/2 Exceptionally detailed implementation: specific NetBox REST endpoints (GET/PATCH with ETag/If-Match), credential resolution flow through OSAC Secret API, host identity derivation from numeric device ID, quarantine behavior for deterministic failures vs. transient retries, and a comprehensive failure handling table covering 11 distinct failure modes with concrete behaviors. All lifecycle operations (FindFreeHost, AssignHost, UnassignHost) are fully specified with step-by-step workflows. Risks are specific technical risks (concurrent claim races, API response changes, credential exposure) with concrete mitigations (ETag/If-Match, pinned images, redacted logs). Drawbacks section steel-mans the operational cost argument.
Testability 2/2 Outstanding 107-scenario test plan across three layers: 65 unit tests (table-driven with in-process TLS mock server), 30 integration tests (19 envtest + 1 Helm + 10 real Community API against pinned 4.6.10 and 4.7.1 images), and 12 E2E tests (real NetBox container in Kind cluster). Each scenario has Setup/Action/Expected structure with stable TC-IDs. Tests cover credential safety, race conditions, crash recovery, schema validation, and cross-backend non-regression. Graduation criteria are measurable: Dev Preview (unit + integration pass), Tech Preview (real Community API + E2E pass), GA (complete testplan + ops docs). Requirement traceability matrix maps PRD requirements to specific test scenarios.
Scope 2/2 Clear boundaries: in-tree NetBox backend implementing existing inventory.Client interface, no new CRDs or tenant-facing APIs. Goals are user-visible outcomes (safe concurrent allocation, credential isolation, selector semantics). Non-goals explicitly exclude device management, OS provisioning, status write-back, admin listing, and credential rotation. Five real alternatives analyzed and rejected with rationale. PRD referenced in frontmatter and body. Relevant cross-cutting dimensions addressed: Inventory (core), Provisioning (Metal3 reuse), Networking (AAP hostname fallback). Irrelevant dimensions (Storage, Tenant Onboarding) appropriately omitted per osac-dimensions.md triage guidance.
Architecture 2/2 Follows all OSAC patterns: tenant isolation (osac.openshift.io/tenant) and owner-reference annotations on BMH and runtime Secret resources. No new CRDs; extends internal inventory.Client contract with AllocationContext. Controller patterns followed: finalizer-based cleanup, idempotent operations, persisted ExternalHostID for crash recovery. Dependencies clearly enumerated: OSAC-5618 (Secret API), Metal3 management, fulfillment-service selector projection. Integration with existing services thoroughly described (BMF operator, Metal3 manager, AAP fallback, Enclave Wizard). Upgrade/downgrade and version skew strategies provided. Terminology (BMI, BMH, BMF, ETag) defined and used consistently throughout.

Verdict: A comprehensive, well-structured design that thoroughly addresses architecture, implementation, scope, and testing with exceptional depth across all four criteria.

Feedback: This is a strong design ready for implementation. Minor suggestions: the Observability section could mention whether the two new metrics follow the existing BMF Prometheus naming conventions and whether dashboards/alerts need updating. The Version Skew Strategy could be more specific about minimum supported OSAC-5618 API version requirements. Consider adding a brief note on operational runbook integration for the quarantine workflow (admin restoring staged status after Secret repair).

Critical (0)

None.

Important (0)

None.

Suggestions (3)

  1. Observability section names two new Prometheus counters but does not confirm they follow existing BMF metric naming conventions or whether Grafana dashboards/alert rules need corresponding updates.
  2. Version Skew Strategy could specify the minimum required Secret API version from OSAC-5618 rather than just 'deployed compatibly', to help operators validate compatibility during upgrades.
  3. The quarantine recovery workflow (admin restores device to staged after Secret repair) is described but could reference whether a runbook or operational guide template will be provided as part of the GA graduation criteria.

Structural notes (0)

None.


Review cost

Model: claude-opus-4-6
Cost: $0.6875
Tokens: 1.2k in / 3.0k out
Cache: 202.3k read
Active time: 1m 13s
API calls: 0

@github-actions

Copy link
Copy Markdown

Test Plan Review: TP-289

Score: 6/10 | Verdict: Revise

Dimension Score Notes
Specificity 2/2 Strong throughout. Tests specify exact function names (FindFreeHost, AssignHost, UnassignHost), concrete parameter values (cpu_cores: '16', memory_gb: '64'), specific error messages ('endpoint required', 'NetBox API authentication failed'), precise HTTP status codes, retry counts (3), timeout values (500ms), and expected return types ((nil, nil), (host, nil)). Meets the S=2 calibration standard.
Grounding 1/2 Names Ginkgo/Gomega framework, httptest, Kind cluster, and osac-test-infra repo. One test references 'netbox_test.go / Describe("Configuration")' and overview mentions 'mock HTTP server patterns from existing BCM tests'. However, the vast majority of tests lack specific test file paths, fixture references (no grpc fixture, no k8s_hub_client equivalent), or helper function names. No pointers to existing test patterns to follow (e.g., 'follow pattern in test_bcm_lifecycle.go'). Referencing product
Scope fidelity 1/2 Most functional requirements from the design are covered (inventory.Client interface methods, label matching, idempotency, error handling, tenant transparency, observability). However, significant discrepancies with the design: (1) custom field name is 'osac_assignment_id' in tests vs 'osac_instance_id' in design — tests would assert against the wrong field; (2) device status is 'active' in tests vs 'staged' in design; (3) Prometheus metric names differ entirely (design: 'osac_netbox_*' prefix,
Actionability 1/2 Every test has Setup/Action/Expected structure with concrete values. Integration and E2E tests use numbered steps. Preconditions are generally specified (mock server, Kind cluster, device counts). An engineer could implement most tests from the plan. However, tests lack fixture references or pointers to similar existing tests — the rubric calibration for A=2 requires 'Reference: follow pattern in test_virtual_network_lifecycle.py' style guidance, which is absent. Engineers would need to independ
Consistency 1/2 Summary table counts don't match actual test counts in three categories: Config lists 5 but document has 6 tests, HTTP lists 9 but document has 8, FindFreeHost lists 11 but document has 12. Stated total of 53 should be 54. Kubernetes Events test lists 'HostAllocated' event twice (duplicate entry). The test plan internally uses consistent naming and structure, and test groupings are logical. No TC-ID scheme is used (legacy format), which is acceptable per scoring instructions.

Verdict: Well-structured test plan with strong specificity but undermined by field name and status value mismatches against the design, missing BMC lifecycle test coverage, and lack of test infrastructure grounding.

Feedback: Align the custom field name to 'osac_instance_id' per the design (currently 'osac_assignment_id' throughout) and fix device status from 'active' to 'staged' to match the design's FindFreeHost query. Add unit tests for the BMC credential extraction, BMC Secret creation, and BMH creation steps in AssignHost — these are core to the design's workflow but completely absent from the test plan. Ground the plan in specific test files, fixtures, and helper patterns from bare-metal-fulfillment-operator (e.g., reference existing BCM test files by path, name the mock server setup helpers, point to test patterns to follow).

Critical (2)

  1. Custom field name mismatch: test plan uses 'osac_assignment_id' everywhere but design defines the field as 'osac_instance_id' — tests would assert against a non-existent field
  2. Device status mismatch: tests filter by 'status=active' but design specifies 'status=staged' for allocable devices in the FindFreeHost query — tests would query the wrong device pool

Important (4)

  1. BMC credential extraction, BMC Secret creation, and BMH creation (design AssignHost steps 3, 6, 7) have zero test coverage despite being core to the allocation flow
  2. Prometheus metric names in tests (netbox_host_search_attempts, netbox_assignment_attempts, netbox_assignment_duration_seconds) don't match the design's defined metrics (osac_netbox_hosts_available, osac_netbox_assignment_attempts_total, osac_netbox_api_errors_total)
  3. No grounding in specific test files, fixtures, or helper functions beyond framework-level references — engineers must independently discover test infrastructure patterns
  4. Summary table counts don't match actual test counts (Config: 6 vs 5, HTTP: 8 vs 9, FindFreeHost: 12 vs 11; actual total 54 vs stated 53)

Suggestions (4)

  1. Add test file path references throughout (e.g., 'Location: internal/inventory/netbox_test.go / Describe("AssignHost")') and point to existing BCM test files as patterns to follow
  2. Add unit test for Metal3 management type co-validation at operator startup (design requires inventory.type=netbox AND management.type=metal3)
  3. Fix duplicate 'HostAllocated' event entry in Kubernetes Events test (lines 421 and 423)
  4. Add test for UnassignHost BMH deletion and BMC Secret cleanup steps from the design's deallocation flow

Review cost

Model: claude-opus-4-6
Cost: $0.4991
Tokens: 1.2k in / 8.0k out
Cache: 139.8k read
Active time: 2m 47s
API calls: 0

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
- On success: record `ExternalHostID` in BareMetalInstance status; proceed to power/provisioning

3. **Host Provisioning** (existing Metal3/BMH workflow):
- Create or update Metal3 BareMetalHost for power management

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 need to extract credentials from netbox and create the bmc secret as well ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. I think that in any inventory case that will involved metal3 as management this will be the flow

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
- Rationale: custom field queries via API are cumbersome; client-side filtering is simpler and more flexible
- Pagination: handle large device counts via limit/offset (e.g., fetch 100 at a time)

### Idempotency and Crash Recovery

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 think this section is redundant with "Operator reconciliation" in "Tenant User: Request and Release Bare-Metal Host" section

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated

## Security Considerations

### Credential Handling

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.

this section is almost the same as "TLS and Credential Security" section


No changes to RBAC or tenancy model. Existing BareMetalInstance RBAC applies unchanged.

NetBox backend records assignment identifier (BareMetalInstance UID) in NetBox, not tenant name. Tenant isolation is enforced at the BareMetalInstance API level (fulfillment-service OPA policies); NetBox stores no tenant-identifying data.

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.

same info as in "Tenant Isolation" section

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
Comment thread enhancements/OSAC-1610-netbox-inventory/design.md
@mennyaboush
mennyaboush force-pushed the design/OSAC-4347-netbox-inventory-impl branch from d0f7914 to f359bab Compare September 14, 2026 12:06
@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The pull request adds requirements, design documentation, deployment decisions, lifecycle behavior, and a 53-scenario test plan for an in-tree NetBox inventory backend.

Changes

NetBox inventory backend

Layer / File(s) Summary
Requirements and clarified scope
enhancements/OSAC-1610-netbox-inventory/prd.md, enhancements/OSAC-1610-netbox-inventory/clarifications.md
Defines backend scope, secure configuration, host allocation, tenant transparency, deployment decisions, and responsibility boundaries.
Backend contract and allocation design
enhancements/OSAC-1610-netbox-inventory/design.md
Defines the proposed client operations, configuration, device filtering, label matching, assignment and unassignment, Metal3 integration, retries, recovery, and security behavior.
Deployment and operational lifecycle
enhancements/OSAC-1610-netbox-inventory/design.md
Documents secret and certificate handling, startup validation, Helm and Enclave Wizard configuration, observability, compatibility, rollout, backend switching, and failure operations.
Validation strategy and scenarios
enhancements/OSAC-1610-netbox-inventory/testplan.md, enhancements/OSAC-1610-netbox-inventory/design.md
Defines unit, integration, and E2E coverage for configuration, HTTP behavior, allocation, recovery, observability, interoperability, tenant workflows, and 53 total scenarios.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Suggested labels: risk:ship

Merge Risk: 🟡 Moderate · up to 48272

The approved design could permit duplicate or premature host reuse and defines tests that cannot reliably validate key behavior. These issues should be resolved before merge.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors)

Check name Status Explanation Resolution
No-Hardcoded-Secrets ❌ Error The pull request adds concrete credential-shaped token values to enhancements/OSAC-1610-netbox-inventory/testplan.md. The test setup uses "test-token-123" and the Authorization example repeats it;… Remove the concrete token literals from the test plan. Describe them as fixture-provided synthetic values or use non-credential placeholders, and keep assertions phrased without embedding the token value.
No-Sensitive-Data-In-Logs ❌ Error The new design explicitly proposes logs that can expose sensitive data. design.md requires host_search_label_selector with labels requested by the tenant, even though the design allows permissive,… Remove raw tenant label selectors and configured endpoint URLs/hostnames from logs. Log only safe counts and generic error categories. Do not log raw resource or assignment identifiers unless the implementation guarantees that they are non-…
✅ Passed checks (9 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Weak-Crypto ✅ Passed The PR changes only Markdown design, requirements, clarification, and test-plan documents. An exact scan of all added lines found no MD5, SHA1, DES, 3DES, RC4, Blowfish, ECB, HmacSHA1, custom crypto, …
No-Injection-Vectors ✅ Passed PASS — The reviewed range changes only Markdown design, requirements, clarification, and test-plan documents. The added lines contain no SQL concatenation, shell=True, eval/exec, pickle.loads,…
Container-Privileges ✅ Passed The pull request changes only Markdown documents. The two renamed files are 100% content-preserving, and the two added files contain no Kubernetes/container manifest or any explicit privileged, `hos…
Ai-Attribution ✅ Passed AI use is explicitly mentioned in the PR context and commit message. The sole reviewed commit contains the Red Hat attribution trailer Assisted-by: Claude Code <noreply@anthropic.com>. No `Co-Author…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the OSAC-1610 NetBox inventory backend design, which matches the main purpose of the pull request. The [wip] prefix is acceptable status information.
Full details: No-Hardcoded-Secrets

Explanation

The pull request adds concrete credential-shaped token values to enhancements/OSAC-1610-netbox-inventory/testplan.md. The test setup uses "test-token-123" and the Authorization example repeats it; another scenario uses "secret-token-xyz" and repeats it in the expected output. These values are newly introduced in the reviewed diff and are not in a conventional unit-test file, so the stated unit-test exception does not apply. The scan found no private-key material, embedded URL credentials, or long encoded secret blob.

Full details: No-Sensitive-Data-In-Logs

Explanation

The new design explicitly proposes logs that can expose sensitive data. design.md requires host_search_label_selector with labels requested by the tenant, even though the design allows permissive, tenant-provided values. It also proposes startup and connectivity messages containing the configured NetBox endpoint, which may reveal an internal hostname. These logging behaviors are introduced by this PR. The documents state that no tenant data is logged, but they do not enforce that claim for these fields.

Resolution

Remove raw tenant label selectors and configured endpoint URLs/hostnames from logs. Log only safe counts and generic error categories. Do not log raw resource or assignment identifiers unless the implementation guarantees that they are non-sensitive and appropriately redacted. Update the structured-log examples and tests to assert that tenant-provided values, internal hostnames, credentials, and identifiers are absent.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.


## Open Questions

### NetBox Version Compatibility — CRITICAL: Minor Versions Have Breaking Changes

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.

does the api as a endpint to extract netbox version? It can be queried and enable different code paths in the inventory backend

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
@github-actions

Copy link
Copy Markdown

Test Plan Review: TP-289

Score: 7/10 | Verdict: Revise

Dimension Score Notes
Specificity 2/2 Tests specify concrete API methods (FindFreeHost, AssignHost, UnassignHost), exact parameter values ({cpu_cores: "16", memory_gb: "64"}), specific instance IDs ("inst-123"), HTTP status codes, precise error messages, and detailed return tuples ((host, nil), (nil, nil)). Prometheus metric names and label values are exact. Meets S=2 calibration.
Grounding 1/2 Names Ginkgo/Gomega framework, mentions netbox_test.go, envtest, httptest.Server, Kind cluster, and osac-test-infra repo. However, does not reference specific existing test files or fixtures as implementation patterns (e.g., no 'follow pattern in test_bcm_client_test.go' or existing helper functions). The netbox_test.go reference is the file to be created, not an existing pattern to follow. Stops at G=1.
Scope fidelity 1/2 Most design requirements covered (inventory.Client methods, label matching, idempotency, race conditions, error handling, observability). Gaps: (1) BMC credential extraction from NetBox custom fields and BMC Secret lifecycle (create/delete) during AssignHost/UnassignHost are described in the design but have no unit-level tests; (2) NetBox version compatibility testing is flagged as CRITICAL in the design's Open Questions but not addressed in the test plan; (3) Enclave Wizard pipeline validation
Actionability 2/2 Every test follows a clear Setup/Action/Expected structure with specific parameters and return values. Unit tests name exact methods, arguments, and expected outputs. Integration tests list numbered steps with observable verification points. An engineer can implement these without guessing about inputs or assertions. Meets A=2.
Consistency 1/2 Summary table claims 53 total test scenarios but only 48 are actually documented. Per-section mismatches: Config parsing (6 documented vs 5 claimed), HTTP client (8 vs 9), FindFreeHost (12 vs 11), AssignHost (4 vs 6), UnassignHost (3 vs 4), E2E Stress (1 vs 3). Success Criteria line references '100 concurrent allocations' but the actual stress test describes only 20 concurrent requests with 10 hosts. Cross-backend test is double-counted (in integration total and as separate row).

Verdict: Solid test plan with specific scenarios and clear structure, but count mismatches, missing BMC credential lifecycle tests, and unaddressed NetBox version compatibility testing prevent a Ready verdict.

Feedback: Fix the coverage summary table to match the 48 actually documented tests — the 5 missing tests (AssignHost concurrent scenarios, UnassignHost edge case, stress variants) should either be documented or the table corrected. Add unit tests for BMC credential extraction from NetBox custom fields and BMC Secret create/delete lifecycle, which the design describes as part of AssignHost/UnassignHost but the test plan omits. Ground the plan in existing test patterns: reference specific files in bare-metal-fulfillment-operator (e.g., the BCM client tests) as implementation templates, and name concrete fixtures or helpers the new tests should reuse.

Critical (2)

  1. Summary table claims 53 test scenarios but only 48 are documented; per-section counts (AssignHost 4 vs 6, UnassignHost 3 vs 4, Stress 1 vs 3, Config 6 vs 5, HTTP 8 vs 9, FindFreeHost 12 vs 11) are all wrong — either add the missing tests or fix the table
  2. BMC credential extraction from NetBox custom fields (bmc_username, bmc_password, bmc_address) and BMC Secret create/delete lifecycle are described in the design's AssignHost/UnassignHost flows but have no corresponding test scenarios

Important (3)

  1. Success Criteria states 'Zero double-allocations in stress tests (100 concurrent allocations)' but the actual E2E stress test describes only 20 concurrent requests with 10 hosts — reconcile the numbers or add the 100-concurrent stress test
  2. Design's Open Questions flags NetBox version compatibility as CRITICAL (minor versions have breaking API changes) and calls for CI test matrix against multiple versions — the test plan does not address multi-version testing at all
  3. No references to existing test files or fixtures as patterns to follow — grounding should point to specific files in bare-metal-fulfillment-operator's test suite (e.g., BCM client tests, existing inventory interface tests) so implementers know the codebase conventions

Suggestions (3)

  1. Add unit tests for GetHostNICs behavior after hardware inspection completes (design says it reads from BMH inspection data), not just the initial (nil, nil) stub
  2. Consider adding a test for the Enclave Wizard pipeline validation steps (custom field existence check, Metal3 CRD availability check) described in the design's Configuration section
  3. Adopt TC-IDs (e.g., TC-FR1-01) to improve traceability from test cases back to design requirements

Review cost

Model: claude-opus-4-6
Cost: $0.5825
Tokens: 1.2k in / 6.7k out
Cache: 169.0k read
Active time: 2m 21s
API calls: 0

@mennyaboush
mennyaboush force-pushed the design/OSAC-4347-netbox-inventory-impl branch from f359bab to 5394734 Compare September 14, 2026 12:10
- If unassigned → proceed to step 2
2. Extract BMC credentials: read `bmc_username`, `bmc_password`, `bmc_address` from device custom fields
3. PATCH assignment: update NetBox device with `osac_instance_id = bareMetalInstanceID`. **Include `If-Match: <etag>` header from step 1.** If NetBox returns **412 Precondition Failed** → another process modified the device since our read; return (nil, nil) — treat as race loss.
4. Verify write (sanity check): read device back; confirm `osac_instance_id` matches. This is now a safety net rather than the primary race detection mechanism — the ETag in step 3 prevents concurrent overwrites.

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.

do we really to do it then?

@mennyaboush mennyaboush Sep 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no. you right if we used the IFf-Match the get after write seems redundant. will fix it

Align the NetBox selector contract, Helm Secret lifecycle, allocation state, and test coverage with the reviewed design.

Signed-off-by: MENNY ABOUSH <maboush@maboush-thinkpadt14gen5.raanaii.csb>
Assisted-by: Claude Haiku 4.5 <noreply@anthropic.com>
Assisted-by: Codex <noreply@openai.com>
@mennyaboush
mennyaboush force-pushed the design/OSAC-4347-netbox-inventory-impl branch from 251331b to 59b724b Compare September 17, 2026 14:26

### Input Validation

Label selectors from BareMetalInstance API are user-provided key=value pairs. These are converted to tag slugs and included in NetBox API query URLs. Input validation requirements:

@adriengentil adriengentil Sep 17, 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.

BareMetalInstanceTypes where label selectors lives are created by the cloud admin who is owner on the system, not by tenant users/admins.

The user-facing API is not aware of the inventory system.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

you right. the tenant do not supposed to be aware to the inventory and current design

@adriengentil

adriengentil commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

please avoid to rebase the history, it makes harder to review between changes

Remove the redundant post-write verification step from host allocation flows and clarify the admin-managed selector source.

Assisted-by: Codex <noreply@openai.com>
Signed-off-by: MENNY ABOUSH <maboush@maboush-thinkpadt14gen5.raanaii.csb>
@mennyaboush
mennyaboush requested a review from jkilzi September 22, 2026 09:37
@openshift-ci

openshift-ci Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

@jkilzi: changing LGTM is restricted to collaborators

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci

openshift-ci Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jkilzi, mennyaboush
Once this PR has been reviewed and has the lgtm label, please assign vladikr for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated
`device_type` filter, and it does not extract selectors from the instance
type's hardware fields. Any hardware distinction needed for placement must
be represented by a tag key in the resolved HostSelector.
2. `FindFreeHost` returns an inventory host ID in the existing `<namespace>/<name>` form expected by the controller and Metal3 management client: `<metal3 namespace>/netbox-device-<NetBox device ID>`. The reconciler persists that ID in `ExternalHostID` before calling `AssignHost`, as it does for the other inventory backends. This persisted ID is the recovery pointer: when it is already set, the controller skips `FindFreeHost` and lets `AssignHost` reconcile the NetBox state.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why add metal3 namespace to the external host id here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

maybe it should be discribe at the design more clearly but metal3 identify the BMH with namespace/name while netbox do not use the namespace so we need to make the same adaptation we did at bcm and save the hostId with the namespace for the BMH to continens the correct values at the management client

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Okay, maybe this is already handled some specific way in BCM that I need to review, but I figured the metal3 namespace for this was fixed at the config level so there was no reason to store it anywhere else.

Comment on lines +128 to +140
#### Selector data flow and lifetime

`hostSelector` is a persistent field in the BareMetalInstance **spec**, not a
temporary argument created by the NetBox adapter. Before the CR is created,
fulfillment-service copies the referenced instance type's
`host_label_selector.match_labels` into `spec.selector.hostSelector`. The CRD
requires at least one entry and makes the selector immutable, so the map stays
with that BareMetalInstance for its lifetime, including allocation, provisioning,
deallocation, and controller restarts. The controller uses it for
`FindFreeHost` while no `ExternalHostID` is recorded; after a candidate ID is
persisted, retries use that ID with `AssignHost` and do not select by tags again.
The NetBox client does not fetch or reconstruct the instance type at allocation
time.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Am I missing something or is none of this new? This is how it works today and will be unchanged by this proposal, why mention it?

Comment thread enhancements/OSAC-1610-netbox-inventory/design.md Outdated

**Credential Management:**
- API token stored in the Helm-created Kubernetes Secret `osac-netbox-api-token`, key `token`
- Secret is mounted read-only at `/etc/osac/secrets/<tokenSecret>/`; the client reads `/etc/osac/secrets/<tokenSecret>/token`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Where does this happen? Earlier in the doc there is a struct like this:

type NetBoxOptions struct {
    Endpoint     string `json:"endpoint"`     // https://netbox.example.com
    TokenSecret  string `json:"tokenSecret"`  // Kubernetes Secret name/key token
    CACertSecret string `json:"caCertSecret"` // Optional Secret/key ca.crt
}

I think we can do it either by mounting or with the secret ref in the struct, but not both.


**TLS Configuration:**
- System CA bundle used by default
- Optional custom CA cert provided in the Helm-created `osac-netbox-ca` Secret, key `ca.crt`, and mounted read-only at `/etc/osac/secrets/<caCertSecret>/ca.crt` alongside the token

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Same comment here. Is it mounted or is the secret being read based on the struct info?

management configuration. The existing chart uses `metal3.enabled` for both
Metal3 inventory and management templates, so the implementation must avoid
rendering two objects with the same `secrets.inventoryConfig` name: when both
`netbox.enabled` and `metal3.enabled` are true, the NetBox template owns

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I would expect them to get wrapped together. I don't understand why someone would enable both here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There no need and supposed to failed in case we enabled 2 inventory at the same time.
this section maybe confusing but I see that as both enabled 1 for the inventory and 1 management as it should be.

What is mean to expect them get wrapped together?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Like I wouldn't expect to see netbox.enabled and metal3.enabled with sections for both. I expected to see the config section as you wrote it with just netbox.enabled = true

Specifically the line that's confusing is "when both netbox.enabled and metal3.enabled are true" - I would expect this never to happen and have no reason to happen because the netbox section already has everything we need for metal3 management.

@mennyaboush mennyaboush changed the title OSAC-1610: NetBox Inventory Backend Design [wip] OSAC-1610: NetBox Inventory Backend Design Sep 22, 2026
MENNY ABOUSH added 2 commits September 23, 2026 09:27
Use provider-created custom fields, preserve device names with durable numeric identity, clarify mounted credentials and Metal3 wiring, and specify restart-safe allocation cleanup with aligned coverage.

Assisted-by: Codex <noreply@openai.com>
Signed-off-by: MENNY ABOUSH <maboush@maboush-thinkpadt14gen5.raanaii.csb>
Assisted-by: Codex <noreply@openai.com>
Signed-off-by: MENNY ABOUSH <maboush@maboush-thinkpadt14gen5.raanaii.csb>
@mennyaboush
mennyaboush force-pushed the design/OSAC-4347-netbox-inventory-impl branch from 55a7ad3 to 10df395 Compare September 24, 2026 10:21
Align the NetBox test plan with system-scoped, device-label BMC Secret resolution and credential failure handling.

Assisted-by: Codex <noreply@openai.com>
Signed-off-by: MENNY ABOUSH <maboush@maboush-thinkpadt14gen5.raanaii.csb>
configuration.
- NetBox device names are optional metadata. The stable OSAC identity is
derived from the numeric device ID as netbox-<id>; endpoint or Metal3
namespace changes require draining affected instances.

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.

metal3 namespace change is not expected. What means "endpoint change"?

Starting state: the provider has a reachable NetBox deployment and a configured
OSAC Secret API.

1. The administrator creates the required NetBox device and scalar capability

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.

"scalar" ?

Comment on lines +114 to +115
address and boot MAC to each corresponding NetBox device. Raw credentials
and Secret IDs are never entered in NetBox.

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.

Suggested change
address and boot MAC to each corresponding NetBox device. Raw credentials
and Secret IDs are never entered in NetBox.
address and boot MAC to each corresponding NetBox device.

address and boot MAC to each corresponding NetBox device. Raw credentials
and Secret IDs are never entered in NetBox.
3. The administrator configures the NetBox endpoint, API token, CA material,
Secret API endpoint, and controller credentials in the deployment values.

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 secret API endpoint might be configured at install time, we should know the URL of the fulfillment-service at install time.

@adriengentil adriengentil 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.

few comments, but I think it's going to the right direction

address and boot MAC to each corresponding NetBox device. Raw credentials
and Secret IDs are never entered in NetBox.
3. The administrator configures the NetBox endpoint, API token, CA material,
Secret API endpoint, and controller credentials in the deployment values.

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.

Suggested change
Secret API endpoint, and controller credentials in the deployment values.
Secret API endpoint, and controller credentials in the OSAC deployment values.

3. The administrator configures the NetBox endpoint, API token, CA material,
Secret API endpoint, and controller credentials in the deployment values.
4. The operator validates connectivity and fixed NetBox fields when it starts.
Capability fields are validated when they are used by a selector.

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.

not sure I understand this sentence

| osac_managed=true | Provider | Enrolls a device in the OSAC pool |
| status=staged/active/failed | OSAC | Available, claimed, or quarantined state |
| osac_instance_id | OSAC | BMI UID owning an active claim |
| osac_bmc_address | Provider | Metal3-compatible BMC address |

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 might need to add the equivalent of "osac_interface_macs" https://redhat.atlassian.net/browse/OSAC-5810?focusedCommentId=18731725

created for that allocation, waits for both resources to disappear, and then
conditionally restores status staged and clears the owner. The source OSAC
Secret is not deleted.

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 also need to describe GetHostNICs, it should behave like BCM integration.

Comment on lines +294 to +297
The BMF uses an authenticated private Secret API client. It does not connect
directly to Vault, Thales KMS, or another provider backend. OSAC-5618 provides
the system-scoped Secret authorization; tenant users cannot retrieve the source
Secret data.

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.

Suggested change
The BMF uses an authenticated private Secret API client. It does not connect
directly to Vault, Thales KMS, or another provider backend. OSAC-5618 provides
the system-scoped Secret authorization; tenant users cannot retrieve the source
Secret data.
The BMF uses the authenticated private OSAC Secret API client.

that should be enough

Secret deletion and automatic rotation are not part of this enhancement;
providers must coordinate rotation by their normal secret lifecycle and,
where needed, drain and reassign hosts.

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.

can we state what is the data expected in the secret (json, yaml) and what are the fields ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants