Skip to content

✨ Fields for placement score visibility feature#428

Open
bhperry wants to merge 1 commit intoopen-cluster-management-io:mainfrom
bhperry:placement-decision-score
Open

✨ Fields for placement score visibility feature#428
bhperry wants to merge 1 commit intoopen-cluster-management-io:mainfrom
bhperry:placement-decision-score

Conversation

@bhperry
Copy link
Contributor

@bhperry bhperry commented Mar 11, 2026

Summary

Add fields to support including placement decision score in the status of PlacementDecisions

Related issue(s)

Placement Score Visibility Enhancement

Summary by CodeRabbit

  • New Features
    • Configurable sorting for placement decisions (by cluster name or by score).
    • Rate limiting for score updates to control recalculation frequency.
    • Placement decisions include a computed score for each cluster.
    • Timestamp added to record when placement scores were last updated.

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Warning

Rate limit exceeded

@bhperry has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 34 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1e39f5b6-7091-4420-87cd-ad1ce77732a5

📥 Commits

Reviewing files that changed from the base of the PR and between c0cfd43 and f7b3ac9.

📒 Files selected for processing (5)
  • cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml
  • cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml
  • cluster/v1beta1/types_placement.go
  • cluster/v1beta1/types_placementdecision.go
  • cluster/v1beta1/zz_generated.deepcopy.go

Walkthrough

Added score reporting, sorting, and rate-limiting fields: scoreRateLimit, sortBy, lastScoreUpdateTime on Placements; score on PlacementDecisions. Corresponding Go types and deepcopy logic updated; duplicate type/constant declarations were introduced in one types file.

Changes

Cohort / File(s) Summary
CRD: Placements
cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml
Added scoreRateLimit (string, default "1m", pattern), sortBy (enum `"ClusterName"
CRD: PlacementDecisions
cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml
Added score (integer format int64) to status.decisions.items ClusterDecision and included it in required fields.
Go types
cluster/v1beta1/types_placement.go, cluster/v1beta1/types_placementdecision.go
Added PlacementSortByType and constants (ClusterName, Score); added SortBy and ScoreRateLimit to PlacementSpec; added LastScoreUpdateTime to PlacementStatus; added Score int64 to ClusterDecision. Note: duplicate declarations of PlacementSortByType and its constants present.
Generated deepcopy
cluster/v1beta1/zz_generated.deepcopy.go
Updated DeepCopyInto to nil-check and deep-copy PlacementStatus.LastScoreUpdateTime.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

lgtm, approved

Suggested reviewers

  • deads2k
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding fields for the placement score visibility feature.
Description check ✅ Passed The description provides a clear summary and links to the related enhancement issue, meeting the template requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 11, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

@bhperry bhperry changed the title ✨ [WIP] Fields for placement score visibility feature ✨ Fields for placement score visibility feature Mar 12, 2026
@bhperry bhperry marked this pull request as ready for review March 12, 2026 19:15
@openshift-ci openshift-ci bot requested review from deads2k and qiujian16 March 12, 2026 19:15
Copy link

@coderabbitai coderabbitai bot left a comment

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)
cluster/v1beta1/types_placementdecision.go (1)

61-63: Add +optional marker and omitempty to the Score field for API consistency.

The Score field lacks the +optional kubebuilder marker. Looking at the corresponding CRD schema, score is not in the required list (only clusterName and reason are required). For consistency with the CRD and API documentation clarity, consider adding the +optional marker and omitempty to the JSON tag.

♻️ Proposed fix
-	// Score is the computed score for the cluster based on configured prioritizers
-	Score int64 `json:"score"`
+	// Score is the computed score for the cluster based on configured prioritizers
+	// +optional
+	Score int64 `json:"score,omitempty"`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placementdecision.go` around lines 61 - 63, The Score
field in the PlacementDecision type is missing the kubebuilder +optional marker
and omitempty JSON tag; update the Score field declaration in
types_placementdecision.go by adding the comment marker "+optional" immediately
above the Score field and change the struct tag from `json:"score"` to
`json:"score,omitempty"` so the generated CRD and JSON serialization match the
API schema (field name: Score).
cluster/v1beta1/types_placement.go (1)

103-119: Consider adding integration test coverage for the new fields.

Based on the relevant code snippets, the existing integration tests in test/integration/api/placement_test.go do not exercise the new SortBy, ScoreRateLimit, or LastScoreUpdateTime fields. While this PR focuses on API field definitions, test coverage would help validate the schema and prevent regressions.

Would you like me to open an issue to track adding test coverage for these new fields?

Also applies to: 185-194, 473-475

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placement.go` around lines 103 - 119, The integration
tests don't cover the newly added API fields SortBy (type PlacementSortByType),
ScoreRateLimit (string), and LastScoreUpdateTime; add tests in
test/integration/api/placement_test.go that create/update Placement resources
asserting the schema round-trips and behavior: verify SortBy accepts the default
and "Score"/"ClusterName" values and is persisted, verify ScoreRateLimit accepts
the validated duration pattern and is persisted, and verify LastScoreUpdateTime
is set/updated when score-related updates occur; reference PlacementSortByType,
SortBy, ScoreRateLimit, and LastScoreUpdateTime in your test cases and include
assertions for JSON serialization/deserialization and API response fields to
prevent regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml`:
- Around line 435-442: The regex for the scoreRateLimit CRD field is wrong
because the character class `[h|m|s]` treats `|` as a literal; update the
pattern for the scoreRateLimit field (the YAML key named scoreRateLimit and its
pattern entry) to use a proper character class without pipes (e.g., `[hms]`) so
the pattern matches numeric values followed by h, m, or s as intended.
- Around line 443-454: The description for the CRD field sortBy contains a
typographical error: change "orderd" to "ordered" in the multi-line description
under the sortBy spec (the block that begins with "SortBy sets the sort order
for decisions." and includes the lines starting "If sortBy is ..."); update the
string so it reads "If sortBy is \"ClusterName\", decisions will be ordered
alphanumerically by cluster name" to correct the typo while leaving the rest of
the text and enum/type definitions unchanged.

In `@cluster/v1beta1/types_placement.go`:
- Around line 103-111: Fix the typo in the comment for the SortBy field: change
"orderd" to "ordered" in the comment that describes the sorting behavior above
the SortBy PlacementSortByType `json:"sortBy,omitempty"` declaration (reference
symbols: SortBy, PlacementSortByType).
- Around line 113-119: The kubebuilder validation Pattern on the ScoreRateLimit
field is wrong because it uses '|' inside a character class; update the
annotation on ScoreRateLimit to use a proper alternation or character class
(e.g. change Pattern="^[0-9]+[h|m|s]$" to Pattern="^[0-9]+(h|m|s)$" or
Pattern="^[0-9]+[hms]$") so only valid duration suffixes are accepted; modify
the struct tag on ScoreRateLimit accordingly and run codegen/validation to
confirm.

---

Nitpick comments:
In `@cluster/v1beta1/types_placement.go`:
- Around line 103-119: The integration tests don't cover the newly added API
fields SortBy (type PlacementSortByType), ScoreRateLimit (string), and
LastScoreUpdateTime; add tests in test/integration/api/placement_test.go that
create/update Placement resources asserting the schema round-trips and behavior:
verify SortBy accepts the default and "Score"/"ClusterName" values and is
persisted, verify ScoreRateLimit accepts the validated duration pattern and is
persisted, and verify LastScoreUpdateTime is set/updated when score-related
updates occur; reference PlacementSortByType, SortBy, ScoreRateLimit, and
LastScoreUpdateTime in your test cases and include assertions for JSON
serialization/deserialization and API response fields to prevent regressions.

In `@cluster/v1beta1/types_placementdecision.go`:
- Around line 61-63: The Score field in the PlacementDecision type is missing
the kubebuilder +optional marker and omitempty JSON tag; update the Score field
declaration in types_placementdecision.go by adding the comment marker
"+optional" immediately above the Score field and change the struct tag from
`json:"score"` to `json:"score,omitempty"` so the generated CRD and JSON
serialization match the API schema (field name: Score).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f18b9bb0-9d2b-43c4-9740-8a31d813a67e

📥 Commits

Reviewing files that changed from the base of the PR and between d71eec7 and d809d29.

📒 Files selected for processing (5)
  • cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml
  • cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml
  • cluster/v1beta1/types_placement.go
  • cluster/v1beta1/types_placementdecision.go
  • cluster/v1beta1/zz_generated.deepcopy.go

Comment on lines +103 to +111

// SortBy sets the sort order for decisions.
// It can be "ClusterName", "Score", or "", where "" is "ClusterName" by default.
// If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
// then by cluster name in the event of a tie
// +kubebuilder:default:=ClusterName
// +optional
SortBy PlacementSortByType `json:"sortBy,omitempty"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Minor typo: "orderd" should be "ordered".

Line 106 contains a typo in the comment.

📝 Proposed fix
 	// SortBy sets the sort order for decisions.
 	// It can be "ClusterName", "Score", or "", where "" is "ClusterName" by default.
-	// If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
+	// If sortBy is "ClusterName", decisions will be ordered alphanumerically by cluster name
 	// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
 	// then by cluster name in the event of a tie
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// SortBy sets the sort order for decisions.
// It can be "ClusterName", "Score", or "", where "" is "ClusterName" by default.
// If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
// then by cluster name in the event of a tie
// +kubebuilder:default:=ClusterName
// +optional
SortBy PlacementSortByType `json:"sortBy,omitempty"`
// SortBy sets the sort order for decisions.
// It can be "ClusterName", "Score", or "", where "" is "ClusterName" by default.
// If sortBy is "ClusterName", decisions will be ordered alphanumerically by cluster name
// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
// then by cluster name in the event of a tie
// +kubebuilder:default:=ClusterName
// +optional
SortBy PlacementSortByType `json:"sortBy,omitempty"`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placement.go` around lines 103 - 111, Fix the typo in
the comment for the SortBy field: change "orderd" to "ordered" in the comment
that describes the sorting behavior above the SortBy PlacementSortByType
`json:"sortBy,omitempty"` declaration (reference symbols: SortBy,
PlacementSortByType).

@bhperry bhperry force-pushed the placement-decision-score branch 2 times, most recently from 8585258 to e725dde Compare March 12, 2026 19:30
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
cluster/v1beta1/types_placement.go (1)

104-109: ⚠️ Potential issue | 🟡 Minor

Align the SortBy docs with the actual schema.

Line 105 says "" is accepted, but PlacementSortByType only allows ClusterName and Score, so an explicit empty string will still fail CRD validation. I’d document this as “when unset, defaults to ClusterName” instead. Line 106 also still has the previously flagged orderd typo.

📝 Proposed fix
 	// SortBy sets the sort order for decisions.
-	// It can be "ClusterName", "Score", or "", where "" is "ClusterName" by default.
-	// If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
+	// It can be "ClusterName" or "Score". If unset, "ClusterName" is used by default.
+	// If sortBy is "ClusterName", decisions will be ordered alphanumerically by cluster name.
 	// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
 	// then by cluster name in the event of a tie

Verify the generated schema still only permits the two enum values and does not admit an explicit empty string:

#!/bin/bash
set -euo pipefail

fd '0000_02_clusters\.open-cluster-management\.io_placements\.crd\.yaml$' -x sh -c '
  sed -n "/sortBy:/,/scoreRateLimit:/p" "$1"
' sh {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placement.go` around lines 104 - 109, Update the SortBy
field docs to match the schema: remove the claim that an explicit "" is accepted
and instead state that when unset it defaults to ClusterName; fix the typo
"orderd" to "ordered"; keep the kubebuilder default tag
(+kubebuilder:default:=ClusterName) and ensure PlacementSortByType's enum
remains only "ClusterName" and "Score" so CRD validation still rejects an
explicit empty string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@cluster/v1beta1/types_placement.go`:
- Around line 104-109: Update the SortBy field docs to match the schema: remove
the claim that an explicit "" is accepted and instead state that when unset it
defaults to ClusterName; fix the typo "orderd" to "ordered"; keep the
kubebuilder default tag (+kubebuilder:default:=ClusterName) and ensure
PlacementSortByType's enum remains only "ClusterName" and "Score" so CRD
validation still rejects an explicit empty string.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3a7b2586-fbd9-43ff-aedc-da0a97d8acd2

📥 Commits

Reviewing files that changed from the base of the PR and between d809d29 and 8585258.

📒 Files selected for processing (5)
  • cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml
  • cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml
  • cluster/v1beta1/types_placement.go
  • cluster/v1beta1/types_placementdecision.go
  • cluster/v1beta1/zz_generated.deepcopy.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • cluster/v1beta1/zz_generated.deepcopy.go
  • cluster/v1beta1/types_placementdecision.go
  • cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml

@bhperry bhperry force-pushed the placement-decision-score branch from e725dde to c0cfd43 Compare March 12, 2026 19:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
cluster/v1beta1/types_placement.go (1)

103-111: ⚠️ Potential issue | 🟡 Minor

Minor typo: "orderd" should be "ordered".

Line 106 contains a typo in the SortBy field comment.

📝 Proposed fix
 	// SortBy sets the sort order for decisions.
 	// It can be "ClusterName", or "Score".
-	// If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
+	// If sortBy is "ClusterName", decisions will be ordered alphanumerically by cluster name
 	// If sortBy is "Score", decisions will be ordered numerically in descending order by score,
 	// then by cluster name in the event of a tie
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placement.go` around lines 103 - 111, Fix the typo in
the comment for the SortBy field: change "orderd" to "ordered" in the docstring
above the SortBy PlacementSortByType `json:"sortBy,omitempty"` declaration so
the comment correctly reads that decisions will be ordered alphanumerically by
cluster name; leave all other wording and annotations intact.
cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml (1)

443-454: ⚠️ Potential issue | 🟡 Minor

Minor typo: "orderd" should be "ordered".

Line 448 contains a typo in the sortBy description that should be fixed.

📝 Proposed fix
-                If sortBy is "ClusterName", decisions will be orderd alphanumerically by cluster name
+                If sortBy is "ClusterName", decisions will be ordered alphanumerically by cluster name
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml`
around lines 443 - 454, The description for the sortBy field contains a typo
("orderd")—update the description string for the sortBy property (the SortBy
description in the CRD for sortBy / enum ClusterName/Score) to replace "orderd"
with "ordered" so the sentence reads "decisions will be ordered alphanumerically
by cluster name"; leave the rest of the description and enum values unchanged.
🧹 Nitpick comments (1)
cluster/v1beta1/types_placementdecision.go (1)

61-64: Consider adding omitempty to the Score JSON tag for consistency.

The field is marked +optional but the JSON tag json:"score" lacks omitempty. This means a score of 0 will always be serialized in the JSON output, even when the score hasn't been computed. If 0 is a valid score value and should be distinguishable from "no score," the current approach is correct. Otherwise, consider adding omitempty to avoid always serializing the zero value.

♻️ Suggested change if omitempty is desired
 	// Score is the computed score for the cluster based on configured prioritizers
 	// +optional
-	Score int64 `json:"score"`
+	Score int64 `json:"score,omitempty"`

Please verify whether 0 is a valid score that should be distinguishable from "score not set." If so, the current implementation is correct. If 0 always means "unset," adding omitempty would be more appropriate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cluster/v1beta1/types_placementdecision.go` around lines 61 - 64, The Score
field in the PlacementDecision struct is marked +optional but its JSON tag is
json:"score", so zero (0) will always be serialized; if a zero score should be
treated as "unset" update the struct field Score int64 JSON tag to include
omitempty (json:"score,omitempty") to avoid emitting zero values, otherwise
leave it as-is if 0 is a valid computed score that must be distinguishable from
unset.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml`:
- Around line 443-454: The description for the sortBy field contains a typo
("orderd")—update the description string for the sortBy property (the SortBy
description in the CRD for sortBy / enum ClusterName/Score) to replace "orderd"
with "ordered" so the sentence reads "decisions will be ordered alphanumerically
by cluster name"; leave the rest of the description and enum values unchanged.

In `@cluster/v1beta1/types_placement.go`:
- Around line 103-111: Fix the typo in the comment for the SortBy field: change
"orderd" to "ordered" in the docstring above the SortBy PlacementSortByType
`json:"sortBy,omitempty"` declaration so the comment correctly reads that
decisions will be ordered alphanumerically by cluster name; leave all other
wording and annotations intact.

---

Nitpick comments:
In `@cluster/v1beta1/types_placementdecision.go`:
- Around line 61-64: The Score field in the PlacementDecision struct is marked
+optional but its JSON tag is json:"score", so zero (0) will always be
serialized; if a zero score should be treated as "unset" update the struct field
Score int64 JSON tag to include omitempty (json:"score,omitempty") to avoid
emitting zero values, otherwise leave it as-is if 0 is a valid computed score
that must be distinguishable from unset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cf904a82-02c2-44b2-aca4-c55c68dd0932

📥 Commits

Reviewing files that changed from the base of the PR and between 8585258 and c0cfd43.

📒 Files selected for processing (5)
  • cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml
  • cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml
  • cluster/v1beta1/types_placement.go
  • cluster/v1beta1/types_placementdecision.go
  • cluster/v1beta1/zz_generated.deepcopy.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cluster/v1beta1/0000_03_clusters.open-cluster-management.io_placementdecisions.crd.yaml

@bhperry bhperry force-pushed the placement-decision-score branch from c0cfd43 to f7b3ac9 Compare March 12, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant