Skip to content

HYPERFLEET-1345 - fix: Address bugs from PR#288#310

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift-hyperfleet:mainfrom
ma-hill:HYPERFLEET-1345-2
Jul 23, 2026
Merged

HYPERFLEET-1345 - fix: Address bugs from PR#288#310
openshift-merge-bot[bot] merged 1 commit into
openshift-hyperfleet:mainfrom
ma-hill:HYPERFLEET-1345-2

Conversation

@ma-hill

@ma-hill ma-hill commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes 3 bugs from PR #288 code review. These include updating reference detection to list out all references for a specific resource, a missing validation for the kind field in reference requests, and error message to use name instead of UUID.

HYPERFLEET-1345

Changes

  • Renamed FindReferencers to FindReferencerss in the DAO layer and removed LIMIT 1, so the 409 conflict error on delete now lists all resources blocking the deletion instead of just one
  • Fixed the delete conflict error message to display the target resource's name instead of its UUID
  • Added validation in validateReferences to reject reference requests where the client-provided kind does not match the registry's expected TargetKind

Notes

Bugs #1 and #5 are already complete
#288

Bug 1 — False doc comment claiming circular reference detection
File: pkg/registry/registry.go
The doc comment added by PR #288 claims Validate() detects circular required references but the function body has no cycle detection code. A circular required ref config passes Validate() silently and only fails at runtime.
Fix: implement DFS cycle detection, or remove the false claim and document the limitation.

#306

Bug 5 -- Impact (not in diff) — references-only PATCH returns 400
File: pkg/handlers/validation.go
validatePatchRequest only checks Spec and Labels, not References. PR #288 added PATCH support for references but did not update the handler validator. A references-only PATCH returns 400. Fix: update validatePatchRequest to accept requests where only References is non-nil.

Test Plan

  • Unit tests updated for FindReferencers rename and new return type
  • make verify-all passes
  • make test-integration passes
  • make lint passes

@openshift-ci
openshift-ci Bot requested review from mliptak0 and vkareh July 23, 2026 17:23
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The DAO referencer lookup now returns all matching non-deleted resources. Resource deletion reports every inbound reference with kind and name details. Reference validation rejects mismatched or empty target kinds. Mocks, documentation, unit tests, and integration tests were updated for the new contract and behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ResourceService
  participant ResourceDao
  participant SQLDatabase
  participant APIClient
  ResourceService->>ResourceDao: FindReferencers(targetID)
  ResourceDao->>SQLDatabase: Query all matching non-deleted resources
  SQLDatabase-->>ResourceDao: Referencer rows
  ResourceDao-->>ResourceService: Resource summaries
  ResourceService-->>APIClient: 409 Conflict listing referencers
Loading

Suggested reviewers: mliptak0, vkareh

🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is generic and only loosely describes the changes, so it does not clearly communicate the main fix. Use a specific title like "Fix resource reference conflict handling and kind validation".
✅ Passed checks (9 passed)
Check name Status Explanation
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.
Sec-02: Secrets In Log Output ✅ Passed No non-test/example log or fmt.Print* call logs password/token/secret/credential; only redacted connection_string logging found. CWE-532 not triggered.
No Hardcoded Secrets ✅ Passed No hardcoded secrets, embedded creds, private keys, or apiKey/secret/token/password literals were found in the touched files (CWE-798 scan clean).
No Weak Cryptography ✅ Passed PASS: No crypto/md5, des, rc4, SHA1-for-security, ECB, custom crypto, or secret comparisons found in touched files. No CWE-327/CWE-208 exposure.
No Injection Vectors ✅ Passed Diff adds only parameterized GORM queries and kind validation; no new CWE-89/78/79/502 patterns in non-test code.
No Privileged Containers ✅ Passed HEAD changes only Go code/tests; no Kubernetes/OpenShift manifests, Helm templates, or Dockerfiles were modified, so no CWE-250/CWE-266 privileged settings were introduced.
No Pii Or Sensitive Data In Logs ✅ Passed No added logger/fmt print statements in the changed hunks; only DAO lookup, conflict text, and validation changed. No CWE-532 exposure found.
Description check ✅ Passed The description matches the changeset: all-references delete conflicts, name-based errors, and kind validation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

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

@hyperfleet-ci-bot

hyperfleet-ci-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

Risk Score: 1 — risk/low

Signal Detail Points
PR size 84 lines +0
Sensitive paths none +0
Test coverage Missing tests for: pkg/api pkg/dao pkg/dao/mocks +1

Computed by hyperfleet-risk-scorer

@ma-hill
ma-hill force-pushed the HYPERFLEET-1345-2 branch from dece48d to c914418 Compare July 23, 2026 17:25

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
pkg/dao/resource.go (1)

199-200: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Synchronize the architecture contract for plural referencers.

The linked architecture document still describes FindReferencers as returning only the first referencer in lines 448-451 and 1067-1083. Update those comments and examples so future implementations do not reintroduce LIMIT(1).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/dao/resource.go` around lines 199 - 200, Update the architecture
documentation sections describing FindReferencers to state that it returns all
matching referencers, not only the first, and revise the related examples
accordingly. Preserve the method’s plural-result contract and explicitly avoid
documenting or implying LIMIT(1).

Source: Linked repositories

pkg/services/resource_test.go (1)

2199-2206: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the all-referencers and name-based conflict contract.

This test supplies only one referencer and does not assert that the target’s name is used instead of its UUID. Add at least two referencers, assert both names appear, assert target.Name appears, and assert target.ID does not.

As per path instructions, critical changed logic paths should have regression coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/services/resource_test.go` around lines 2199 - 2206, Update the Delete
conflict test around mockDao.FindReferencersResult to include at least two
referencers, then assert both referencer names and the target’s Name appear in
svcErr.Reason. Add an assertion that target.ID is absent, preserving the
existing HTTP 409 validation.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/dao/resource.go`:
- Around line 211-212: Update the error return in the resource lookup flow to
wrap the underlying DAO error with the failed operation and targetID context,
following the project’s Error Model Standard and preserving error unwrapping.
Change the return associated with the visible err check rather than nearby
success-path logic.
- Around line 206-210: Update the query in the ResourceReference lookup around
g2.Model to deduplicate referencers by grouping on resources.id, resources.kind,
and resources.name before scanning into summaries. Preserve the existing target,
deletion-status filters, join, and selected fields.

In `@pkg/services/resource.go`:
- Around line 986-991: Update the kind validation condition in the reference
validation flow around rd.TargetKind so an empty ref.Kind is accepted as the
documented backward-compatible omission, while non-empty kinds must still match
rd.TargetKind and return the existing validation error otherwise.

In `@test/integration/resource_references_test.go`:
- Around line 523-533: Add fatal guards in the resource-reference tests before
dereferencing potentially nil results: after creating the target in the current
test and in TestResourceReferences_CreateEmptyKind, fail with t.Fatal/t.Fatalf
when target creation returns an error; after creating the source, fail
immediately if validation unexpectedly succeeds before accessing svcErr.HTTPCode
or Reason. Preserve the existing status and reason assertions once svcErr is
confirmed non-nil.

---

Nitpick comments:
In `@pkg/dao/resource.go`:
- Around line 199-200: Update the architecture documentation sections describing
FindReferencers to state that it returns all matching referencers, not only the
first, and revise the related examples accordingly. Preserve the method’s
plural-result contract and explicitly avoid documenting or implying LIMIT(1).

In `@pkg/services/resource_test.go`:
- Around line 2199-2206: Update the Delete conflict test around
mockDao.FindReferencersResult to include at least two referencers, then assert
both referencer names and the target’s Name appear in svcErr.Reason. Add an
assertion that target.ID is absent, preserving the existing HTTP 409 validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 14da0023-d2ad-49c3-a5f9-e55bc8b30029

📥 Commits

Reviewing files that changed from the base of the PR and between 913cd01 and dece48d.

📒 Files selected for processing (6)
  • pkg/api/resource_reference.go
  • pkg/dao/mocks/resource.go
  • pkg/dao/resource.go
  • pkg/services/resource.go
  • pkg/services/resource_test.go
  • test/integration/resource_references_test.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)

Comment thread pkg/dao/resource.go
Comment thread pkg/dao/resource.go
Comment on lines 211 to 212
if err != nil {
return nil, err

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Wrap the DAO error with target context.

Returning nil, err loses the failed operation and target ID at this boundary. Use the project’s error-wrapping convention, such as fmt.Errorf("find referencers for target %q: %w", targetID, err).

As per path instructions, errors must be wrapped per the Error Model Standard; a raw error return is not sufficient.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/dao/resource.go` around lines 211 - 212, Update the error return in the
resource lookup flow to wrap the underlying DAO error with the failed operation
and targetID context, following the project’s Error Model Standard and
preserving error unwrapping. Change the return associated with the visible err
check rather than nearby success-path logic.

Source: Path instructions

Comment thread pkg/services/resource.go
Comment on lines +523 to +533
target, svcErr := svc.Create(t.Context(), "RefTarget",
newRefTestResource("RefTarget", fmt.Sprintf("target-wk-%s", uuid.NewString()[:8])), nil)
Expect(svcErr).To(BeNil())

sourceName := fmt.Sprintf("source-wk-%s", uuid.NewString()[:8])
refs := makeRefs("dep", struct{ id, kind string }{target.ID, "WrongKind"})

_, svcErr = svc.Create(t.Context(), "RefSource", newRefTestResource("RefSource", sourceName), refs)
Expect(svcErr).NotTo(BeNil(), "wrong kind should fail validation")
Expect(svcErr.HTTPCode).To(Equal(400))
Expect(svcErr.Reason).To(ContainSubstring("does not match expected target kind"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Prevent nil dereferences after non-fatal assertions.

Expect does not stop execution. If target creation fails, target.ID can panic; if validation unexpectedly succeeds, svcErr.HTTPCode can panic instead of reporting the intended failure (CWE-476). Use t.Fatal/t.Fatalf guards before dereferencing in both tests.

Proposed fix
 target, svcErr := svc.Create(...)
-Expect(svcErr).To(BeNil())
+if svcErr != nil || target == nil {
+	t.Fatalf("creating reference target failed: %v", svcErr)
+}

 ...

 _, svcErr = svc.Create(...)
-Expect(svcErr).NotTo(BeNil(), "wrong kind should fail validation")
+if svcErr == nil {
+	t.Fatal("wrong kind should fail validation")
+}

Apply the equivalent guards to TestResourceReferences_CreateEmptyKind.

Also applies to: 540-550

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integration/resource_references_test.go` around lines 523 - 533, Add
fatal guards in the resource-reference tests before dereferencing potentially
nil results: after creating the target in the current test and in
TestResourceReferences_CreateEmptyKind, fail with t.Fatal/t.Fatalf when target
creation returns an error; after creating the source, fail immediately if
validation unexpectedly succeeds before accessing svcErr.HTTPCode or Reason.
Preserve the existing status and reason assertions once svcErr is confirmed
non-nil.

Source: Path instructions

@ma-hill
ma-hill force-pushed the HYPERFLEET-1345-2 branch from c914418 to b7fa156 Compare July 23, 2026 17:33

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

♻️ Duplicate comments (1)
pkg/services/resource.go (1)

986-991: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore backward-compatible empty-kind handling.

The service rejects empty kind, while the integration test reinforces that regression by expecting HTTP 400. Empty kind must be accepted; only non-empty mismatches should fail validation.

  • pkg/services/resource.go#L986-L991: change the condition to ref.Kind != "" && ref.Kind != rd.TargetKind.
  • test/integration/resource_references_test.go#L526-L527: remove EmptyKind from invalid-kind cases and assert successful creation separately.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/services/resource.go` around lines 986 - 991, Restore empty-kind
compatibility in the validation around the reference kind check in
pkg/services/resource.go lines 986-991 by rejecting only non-empty kinds that
differ from rd.TargetKind. Update test/integration/resource_references_test.go
lines 526-527 to remove EmptyKind from invalid-kind cases and add a separate
assertion that creation with an empty kind succeeds.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@pkg/services/resource.go`:
- Around line 986-991: Restore empty-kind compatibility in the validation around
the reference kind check in pkg/services/resource.go lines 986-991 by rejecting
only non-empty kinds that differ from rd.TargetKind. Update
test/integration/resource_references_test.go lines 526-527 to remove EmptyKind
from invalid-kind cases and add a separate assertion that creation with an empty
kind succeeds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 4bc11bd4-71c4-4925-aa3c-76c1ba8b5f28

📥 Commits

Reviewing files that changed from the base of the PR and between c914418 and b7fa156.

📒 Files selected for processing (6)
  • pkg/api/resource_reference.go
  • pkg/dao/mocks/resource.go
  • pkg/dao/resource.go
  • pkg/services/resource.go
  • pkg/services/resource_test.go
  • test/integration/resource_references_test.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/services/resource_test.go
  • pkg/dao/resource.go
  • pkg/dao/mocks/resource.go

@ma-hill

ma-hill commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@ma-hill
ma-hill marked this pull request as draft July 23, 2026 17:41
@ma-hill
ma-hill force-pushed the HYPERFLEET-1345-2 branch from b7fa156 to 84dbb27 Compare July 23, 2026 18:09
@ma-hill
ma-hill marked this pull request as ready for review July 23, 2026 18:10
@openshift-ci
openshift-ci Bot requested review from Ruclo and rh-amarin July 23, 2026 18:10
@kuudori

kuudori commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kuudori

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

The pull request process is described 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

@openshift-merge-bot
openshift-merge-bot Bot merged commit 2cda293 into openshift-hyperfleet:main Jul 23, 2026
9 checks passed
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.

2 participants