Skip to content

HYPERFLEET-1160 - feat: separate resource_labels table for generic resource labels#270

Open
kuudori wants to merge 1 commit into
openshift-hyperfleet:mainfrom
kuudori:HYPERFLEET-1160-feat-resource-labels
Open

HYPERFLEET-1160 - feat: separate resource_labels table for generic resource labels#270
kuudori wants to merge 1 commit into
openshift-hyperfleet:mainfrom
kuudori:HYPERFLEET-1160-feat-resource-labels

Conversation

@kuudori

@kuudori kuudori commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace labels JSONB column on resources table with dedicated resource_labels table (composite PK (resource_id, key), FK with CASCADE delete)
  • Add ResourceLabel model, ResourceLabelDao with delete+insert ReplaceLabels, preload labels on all DAO read methods
  • Update service layer: Create/Patch call ReplaceLabels explicitly (DAO uses Omit(clause.Associations))
  • Block labels.xxx TSL search for Resource entities until JOIN-based query support added

Why

JSONB cannot enforce label key uniqueness at DB level, doesn't support efficient label-filter queries without GIN indexes, and conflates user-writable fields with system fields. Separate table enforces uniqueness via composite PK and enables indexed lookups. Per design doc §4.1-4.2.

Test plan

  • All unit tests pass (make test — 1314 tests)
  • All integration tests pass (make test-integration — 237 tests, 3 skipped)
  • Lint clean (golangci-lint — 0 issues)
  • Helm chart tests pass
  • Label round-trip verified: create→get→list→patch flows in channel/version integration tests
  • TestVersionList/ListByLabel skipped — TSL parser needs changes for JOIN-based label queries on separate table

Ticket

https://redhat-internal.atlassian.net/browse/HYPERFLEET-1160

@openshift-ci openshift-ci Bot requested review from Mischulee and tirthct July 2, 2026 15:58
@coderabbitai

coderabbitai Bot commented Jul 2, 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

Walkthrough

Resource labels move from a JSONB field to a normalized resource_labels table with ResourceLabel rows. Presenters now convert between API maps and label slices, services persist labels through a dedicated DAO on create and patch, and query extraction now emits EXISTS predicates against resource_labels. Label handling adds validation, change detection, and soft-delete conflict handling. CWE-20 and CWE-915 apply to label validation and assignment paths.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ResourceService
  participant ResourceDAO
  participant ResourceLabelDAO
  participant Database
  Client->>ResourceService: create or patch resource
  ResourceService->>ResourceDAO: persist resource row
  ResourceService->>ResourceLabelDAO: ReplaceLabels
  ResourceLabelDAO->>Database: delete old labels
  ResourceLabelDAO->>Database: insert label rows
  ResourceService-->>Client: resource with Labels slice
Loading
🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
No Injection Vectors ⚠️ Warning CWE-89: ListByOwner interpolates request ownerID into kind = '%s' AND owner_id = '%s' instead of using bind params. Use parameterized filters (kind = ? AND owner_id = ?) or otherwise bind/escape ownerID; don't compose search text with request data.
✅ Passed checks (10 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the resource_labels table split and generic resource labels change.
Description check ✅ Passed The description matches the changeset, covering the new table, DAO, service updates, and TSL label search limits.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 CWE-532 exposure found; only connection-string logging uses redactPassword(), and no non-test log field/message contains token/password/credential/secret.
No Hardcoded Secrets ✅ Passed No hardcoded credentials, private keys, embedded URL creds, or secret-like literals found in the touched files; strict scan returned 0 hits. CWE-798 not triggered.
No Weak Cryptography ✅ Passed No CWE-327/CWE-208 issues: touched files add no banned primitives, ECB, custom crypto, or secret comparisons; repo scan found none.
No Privileged Containers ✅ Passed No K8s/Helm/Dockerfile changes in diff; no privileged flags found. No new CWE-269/CWE-284 issue.
No Pii Or Sensitive Data In Logs ✅ Passed PASS: No added log statements expose PII/session data; the only logger calls are generic warnings/info with no request bodies or identifiers (CWE-532).
✨ 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 2, 2026

Copy link
Copy Markdown

Risk Score: 3 — risk/medium

Signal Detail Points
PR size 646 lines (>500) +2
Sensitive paths none +0
Test coverage Missing tests for: pkg/api pkg/dao pkg/db pkg/db/migrations plugins/resources +1

Computed by hyperfleet-risk-scorer

@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: 2

🤖 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/api/presenters/resource.go`:
- Around line 123-132: `convertLabelsToModel` currently forwards user-supplied
label keys and values without enforcing the `ResourceLabel` size limits, so
oversized input falls through as a DB constraint error instead of a validation
error. Add boundary validation in `convertLabelsToModel` for key and value
length (matching the `pkg/api/resource_label.go` limits) and return a typed
validation error before persistence. Update `ConvertResource` to propagate the
new error return, and apply the same validation flow in `applyResourcePatch` so
both create and patch paths reject invalid labels consistently.

In `@pkg/db/migrations/202607010001_add_resource_labels.go`:
- Around line 11-31: The migration in the resource labels `Migrate` function
drops `resources.labels` without preserving existing data, and it has no
rollback path. Before the `ALTER TABLE resources DROP COLUMN IF EXISTS labels`
step, backfill `resource_labels` from the existing `resources.labels` JSONB data
in the same migration, then remove the column only after the copy succeeds. Also
add a `Rollback` for this migration that recreates `resources.labels` and
restores data from `resource_labels` using the migration’s existing symbols
(`Migrate`, `Rollback`, `resource_labels`, `resources.labels`) so rollbacks and
rolling deploys remain safe.
🪄 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: 123fe713-ae4e-4454-b5cf-0d71a78eeefd

📥 Commits

Reviewing files that changed from the base of the PR and between 4c4266f and 4a7c909.

📒 Files selected for processing (15)
  • pkg/api/presenters/resource.go
  • pkg/api/presenters/resource_test.go
  • pkg/api/resource.go
  • pkg/api/resource_label.go
  • pkg/dao/resource.go
  • pkg/dao/resource_label.go
  • pkg/db/migrations/202607010001_add_resource_labels.go
  • pkg/db/migrations/migration_structs.go
  • pkg/db/sql_helpers.go
  • pkg/services/resource.go
  • pkg/services/resource_test.go
  • plugins/resources/plugin.go
  • test/integration/channels_test.go
  • test/integration/resource_helpers.go
  • test/integration/versions_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/api/presenters/resource.go Outdated
Comment thread pkg/db/migrations/202607010001_add_resource_labels.go
@kuudori kuudori force-pushed the HYPERFLEET-1160-feat-resource-labels branch 2 times, most recently from 32471e8 to 9f97971 Compare July 2, 2026 18:31

@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: 1

🤖 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/db/migrations/202607010001_add_resource_labels.go`:
- Around line 12-24: The migration in Migrate creates resource_labels and drops
resources.labels, but it never adds the planned (key, value) index. Update the
migration to create that composite index as part of the same transaction, using
the resource_labels table definition and keeping the existing Exec error
handling consistent. Make sure the new index creation is placed near the table
setup so the schema change fully matches the PR objective.
🪄 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: 956f56ad-d3c4-497f-a25b-608e88b90765

📥 Commits

Reviewing files that changed from the base of the PR and between 32471e8 and 9f97971.

📒 Files selected for processing (15)
  • pkg/api/presenters/resource.go
  • pkg/api/presenters/resource_test.go
  • pkg/api/resource.go
  • pkg/api/resource_label.go
  • pkg/dao/resource.go
  • pkg/dao/resource_label.go
  • pkg/db/migrations/202607010001_add_resource_labels.go
  • pkg/db/migrations/migration_structs.go
  • pkg/db/sql_helpers.go
  • pkg/services/resource.go
  • pkg/services/resource_test.go
  • plugins/resources/plugin.go
  • test/integration/channels_test.go
  • test/integration/resource_helpers.go
  • test/integration/versions_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 due to trivial changes (3)
  • pkg/db/migrations/migration_structs.go
  • pkg/api/resource_label.go
  • pkg/db/sql_helpers.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • plugins/resources/plugin.go
  • pkg/api/presenters/resource_test.go
  • pkg/api/resource.go
  • pkg/services/resource_test.go
  • pkg/dao/resource.go
  • test/integration/versions_test.go
  • test/integration/channels_test.go
  • test/integration/resource_helpers.go
  • pkg/api/presenters/resource.go
  • pkg/services/resource.go
  • pkg/dao/resource_label.go

Comment thread pkg/db/migrations/202607010001_add_resource_labels.go
@kuudori kuudori force-pushed the HYPERFLEET-1160-feat-resource-labels branch 2 times, most recently from 6640b02 to c832e6b Compare July 7, 2026 03:27
@openshift-ci

openshift-ci Bot commented Jul 7, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign sherine-k 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

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

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

21-21: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add integration coverage for the new raw-SQL query.

ExistsSoftDeletedByOwner uses hand-written raw SQL with slice binding (kind IN (?)). Per graph context, it's only exercised via a mocked ResourceDao in resource_test.go. A schema rename or GORM dialect quirk here would silently break parent soft-delete conflict detection without any test catching it.

As per path instructions, "New exported functions and critical logic paths SHOULD have tests" (**/*_test.go testing standard).

Also applies to: 116-128

🤖 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` at line 21, Add integration test coverage for
ResourceDao.ExistsSoftDeletedByOwner, since it uses raw SQL with slice binding
and is currently only covered by mocks. Create a real database-backed test that
exercises the actual query path with soft-deleted and non-deleted resources
across multiple kinds, and verify the result changes correctly when
ownerID/kinds match. Place the test alongside the existing ResourceDao tests so
the new exported method and its raw-SQL conflict-check logic are protected from
schema or dialect regressions.

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.

Nitpick comments:
In `@pkg/dao/resource.go`:
- Line 21: Add integration test coverage for
ResourceDao.ExistsSoftDeletedByOwner, since it uses raw SQL with slice binding
and is currently only covered by mocks. Create a real database-backed test that
exercises the actual query path with soft-deleted and non-deleted resources
across multiple kinds, and verify the result changes correctly when
ownerID/kinds match. Place the test alongside the existing ResourceDao tests so
the new exported method and its raw-SQL conflict-check logic are protected from
schema or dialect regressions.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: f9b2307e-25bc-4d99-8047-20cd8c94ff2f

📥 Commits

Reviewing files that changed from the base of the PR and between 6640b02 and c832e6b.

📒 Files selected for processing (16)
  • pkg/api/presenters/resource.go
  • pkg/api/presenters/resource_test.go
  • pkg/api/resource.go
  • pkg/api/resource_label.go
  • pkg/dao/resource.go
  • pkg/dao/resource_label.go
  • pkg/db/migrations/202607010001_add_resource_labels.go
  • pkg/db/migrations/migration_structs.go
  • pkg/db/sql_helpers.go
  • pkg/services/generic.go
  • pkg/services/resource.go
  • pkg/services/resource_test.go
  • plugins/resources/plugin.go
  • test/integration/channels_test.go
  • test/integration/resource_helpers.go
  • test/integration/versions_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 due to trivial changes (1)
  • pkg/db/migrations/migration_structs.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • pkg/api/resource.go
  • pkg/services/resource_test.go
  • pkg/db/migrations/202607010001_add_resource_labels.go
  • pkg/api/resource_label.go
  • test/integration/channels_test.go
  • test/integration/resource_helpers.go
  • pkg/api/presenters/resource_test.go
  • pkg/dao/resource_label.go
  • pkg/services/resource.go
  • pkg/api/presenters/resource.go

@kuudori kuudori force-pushed the HYPERFLEET-1160-feat-resource-labels branch from c832e6b to 6ffe8d7 Compare July 7, 2026 03:40
Replace JSONB labels column on resources with a dedicated resource_labels
table (resource_id, key, value; composite PK, FK with ON DELETE CASCADE).

- Add ResourceLabelDao with delete-all + bulk-insert ReplaceLabels
- Wire label writes through ResourceService Create/Patch
- Add Labels/Conditions preloads to all ResourceDao read methods
- Add ExtractLabelQueries for EXISTS-subquery label filtering
- Generalize extractMatchingQueries from condition-only to reusable
- Restrict label filter operators to = and != (no lexicographic traps)
- Remove validateLabelKey from new table path (key is parameterized)
- Mark legacy JSONB label paths with TODO(HYPERFLEET-1159)
- Enable ListByLabel integration test
@kuudori kuudori force-pushed the HYPERFLEET-1160-feat-resource-labels branch from 6ffe8d7 to 665e255 Compare July 7, 2026 23:28
@openshift-ci

openshift-ci Bot commented Jul 7, 2026

Copy link
Copy Markdown

@kuudori: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/lint 665e255 link true /test lint

Full PR test history. Your PR dashboard.

Details

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. I understand the commands that are listed here.

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.

1 participant