Skip to content

🐛 Use generateName when creating ManifestWorks from ManifestWorkReplicaSet#1394

Open
shivansh-source wants to merge 3 commits intoopen-cluster-management-io:mainfrom
shivansh-source:GenerateName
Open

🐛 Use generateName when creating ManifestWorks from ManifestWorkReplicaSet#1394
shivansh-source wants to merge 3 commits intoopen-cluster-management-io:mainfrom
shivansh-source:GenerateName

Conversation

@shivansh-source
Copy link

@shivansh-source shivansh-source commented Feb 21, 2026

Description

Fixes a naming conflict when ManifestWorkReplicaSets create
ManifestWorks.

Previously, ManifestWorks were created using the
ManifestWorkReplicaSet name directly. This could cause collisions
when multiple ManifestWorkReplicaSets from different namespaces
targeted the same managed cluster namespace.

This PR switches ManifestWork creation to use generateName,
allowing the API server to assign unique names.

Changes

  • Use GenerateName instead of Name when creating ManifestWorks
  • Update deletion logic to locate ManifestWorks via labels
  • Update unit tests to use label-based lookup instead of fixed names

Related Issue

Fixes #1380

Testing

  • Updated existing unit tests
  • go test ./pkg/work/... passes locally

Summary by CodeRabbit

  • Bug Fixes

    • Improved cleanup when clusters are removed by listing and filtering placement-scoped manifest works to ensure all relevant works are deleted.
  • Behavior Changes

    • Manifest work creation now uses server-generated names with a replica-set-derived prefix, altering final resource identifiers.
  • Tests

    • Updated tests and helpers to use listing-based checks and to align fixtures with the new naming behavior.

Signed-off-by: shivansh-source <shivanshsiddhi1234@gmail.com>
@openshift-ci openshift-ci bot requested review from bhperry and elgnay February 21, 2026 11:21
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 21, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

@dosubot
Copy link

dosubot bot commented Feb 21, 2026

Related Documentation

Checked 0 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fce56d and 4854158.

📒 Files selected for processing (1)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go

Walkthrough

Reconcile now lists ManifestWorks by placement/controller labels and deletes those whose namespace matches removed clusters; ManifestWork creation uses GenerateName instead of an explicit Name. Tests and test helpers updated to list by labels and adjust test ManifestWork names.

Changes

Cohort / File(s) Summary
Controller reconciliation
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go
Switched ManifestWork creation to use GenerateName (removed explicit Name). Changed removal flow to list ManifestWorks by placement/controller labels and iterate to delete those whose namespace matches removed clusters instead of Get/Delete by cluster name.
Tests & test helpers
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go, pkg/work/hub/test/helper.go
Added listWorksByMWRS test helper and updated tests to use label-based List to find ManifestWorks; test helper now appends cluster name to generated ManifestWork Name. Replaced direct Get checks with list-and-filter logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

lgtm, approved

Suggested reviewers

  • bhperry
  • elgnay
  • qiujian16
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: switching from Name to GenerateName when creating ManifestWorks from ManifestWorkReplicaSet.
Description check ✅ Passed The description provides a clear summary of the changes, explains the bug being fixed, lists the modifications made, and references the related issue (#1380).
Linked Issues check ✅ Passed The PR successfully addresses issue #1380 by switching to GenerateName for ManifestWork creation and updating deletion/lookup logic to use labels.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the naming conflict issue: ManifestWork creation, deletion logic, label-based lookup, and corresponding test updates.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@shivansh-source
Copy link
Author

/cc @mikeshng

@openshift-ci openshift-ci bot requested a review from mikeshng February 21, 2026 11:22
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1)

157-168: ⚠️ Potential issue | 🔴 Critical

Critical: Broken error handling in the cluster removal loop.

The refactored deletion block has multiple intertwined bugs:

  1. Line 159: Error from listManifestWorksByMWRSetPlacementRef is silently discarded (_).
  2. Line 162: Error return from d.workApplier.Delete() is not captured (confirmed by static analysis: errcheck).
  3. Line 164: errs = append(errs, err) appends a stale err from outer scope (e.g., last Apply or CreateManifestWork call) for every iteration of clusterWorks, regardless of whether the namespace matched. This is leftover code from the pre-refactor single-Delete pattern that doesn't fit the new inner for loop structure.
  4. Line 165: continue is now redundant (continues the inner loop at the last statement).

Net effect: real Delete errors are lost; stale/nil errors are accumulated spuriously.

🐛 Proposed fix
 	for _, cls := range rolloutResult.ClustersRemoved {
 		// Delete manifestWork for removed clusters
-		clusterWorks, _ := listManifestWorksByMWRSetPlacementRef(mwrSet, placementRef.Name, d.manifestWorkLister)
-              for _, mw := range clusterWorks {
-               if mw.Namespace == cls.ClusterName {
-                   d.workApplier.Delete(ctx, mw.Namespace, mw.Name)
-                }
-				errs = append(errs, err)
-				continue
-			}
+		clusterWorks, listErr := listManifestWorksByMWRSetPlacementRef(mwrSet, placementRef.Name, d.manifestWorkLister)
+		if listErr != nil {
+			errs = append(errs, fmt.Errorf("failed to list manifestworks for removed cluster %s: %w", cls.ClusterName, listErr))
+			continue
+		}
+		for _, mw := range clusterWorks {
+			if mw.Namespace == cls.ClusterName {
+				if delErr := d.workApplier.Delete(ctx, mw.Namespace, mw.Name); delErr != nil {
+					errs = append(errs, fmt.Errorf("failed to delete manifestwork %s/%s: %w", mw.Namespace, mw.Name, delErr))
+				}
+			}
+		}
 		existingClusterNames.Delete(cls.ClusterName)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go`
around lines 157 - 168, The loop discards the error from
listManifestWorksByMWRSetPlacementRef and misuses a stale err variable while
ignoring Delete errors; fix by capturing the error from
listManifestWorksByMWRSetPlacementRef (e.g., clusterWorks, err :=
listManifestWorksByMWRSetPlacementRef(...)) and handle/append it to errs if
non-nil, then inside the inner loop call d.workApplier.Delete(ctx, mw.Namespace,
mw.Name) and capture its error (err := d.workApplier.Delete(...)) and only
append that err to errs when non-nil (do not append any outer-scope err); remove
the redundant continue and ensure existingClusterNames.Delete(cls.ClusterName)
is only called after successful processing of the removed cluster entries.
🧹 Nitpick comments (1)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (1)

768-781: Inconsistent indentation and formatting throughout this block.

The mix of tabs and spaces, and flush-left lines (e.g., Line 772-774, Line 781) make this hard to read and will likely fail gofmt checks.

♻️ Proposed formatting fix
-	works, err := listWorksByMWRS(context.TODO(),fWorkClient,"cls1",  mwrSet.Namespace, mwrSet.Name, "place-test1")
-    if err != nil {
-         t.Fatal(err)
-    }
-if len(works) != 0 {
-    t.Fatalf("Expected ManifestWork for old placement to be deleted, but it still exists")
-}
+	works, err := listWorksByMWRS(context.TODO(), fWorkClient, "cls1", mwrSet.Namespace, mwrSet.Name, "place-test1")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(works) != 0 {
+		t.Fatalf("Expected ManifestWork for old placement to be deleted, but it still exists")
+	}
 	// Verify that the ManifestWork from the current placement (place-test2) still exists
-	works, err = listWorksByMWRS( context.TODO(), fWorkClient, "cls2", mwrSet.Namespace, mwrSet.Name, "place-test2",)
-    if err != nil { t.Fatal(err) }
-      if len(works) != 1 {
-       t.Fatalf("Expected ManifestWork for current placement to exist, but got %d", len(works))
-    }
-currentMW := works[0]
+	works, err = listWorksByMWRS(context.TODO(), fWorkClient, "cls2", mwrSet.Namespace, mwrSet.Name, "place-test2")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(works) != 1 {
+		t.Fatalf("Expected ManifestWork for current placement to exist, but got %d", len(works))
+	}
+	currentMW := works[0]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go`
around lines 768 - 781, The test block around listWorksByMWRS has inconsistent
tabs/spaces and misaligned lines (variables: listWorksByMWRS, fWorkClient,
mwrSet, works, currentMW) which will fail gofmt; reformat the entire snippet to
use consistent indentation (tabs per Go conventions), align the if blocks and
error checks, fix spacing around commas/parentheses, and run gofmt/goimports to
apply canonical formatting so the tests compile and pass linter checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go`:
- Around line 866-868: The test's failure message in
manifestworkreplicaset_deploy_test.go incorrectly prints err when checking the
length of works; update the t.Fatalf call in the block that checks if len(works)
!= 1 to report the actual count (use %d with len(works) or include the works
slice) so the message shows how many works were found instead of printing err.
- Around line 876-878: The test's failure message is misleading because it
reports "error: %v", err even though the check is about the length of works for
placement3 and err may be nil or not relevant; update the t.Fatalf in the
manifestworkreplicaset_deploy_test (the assertion that checks if len(works) != 1
for placement3) to report the actual length and/or the contents of works instead
of err (e.g., include len(works) and the works slice or a clear message like
"expected 1 ManifestWork for placement3, got %d: %#v"), so the failure output
accurately reflects the condition being tested.

---

Outside diff comments:
In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go`:
- Around line 157-168: The loop discards the error from
listManifestWorksByMWRSetPlacementRef and misuses a stale err variable while
ignoring Delete errors; fix by capturing the error from
listManifestWorksByMWRSetPlacementRef (e.g., clusterWorks, err :=
listManifestWorksByMWRSetPlacementRef(...)) and handle/append it to errs if
non-nil, then inside the inner loop call d.workApplier.Delete(ctx, mw.Namespace,
mw.Name) and capture its error (err := d.workApplier.Delete(...)) and only
append that err to errs when non-nil (do not append any outer-scope err); remove
the redundant continue and ensure existingClusterNames.Delete(cls.ClusterName)
is only called after successful processing of the removed cluster entries.

---

Nitpick comments:
In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go`:
- Around line 768-781: The test block around listWorksByMWRS has inconsistent
tabs/spaces and misaligned lines (variables: listWorksByMWRS, fWorkClient,
mwrSet, works, currentMW) which will fail gofmt; reformat the entire snippet to
use consistent indentation (tabs per Go conventions), align the if blocks and
error checks, fix spacing around commas/parentheses, and run gofmt/goimports to
apply canonical formatting so the tests compile and pass linter checks.

@mikeshng
Copy link
Member

return &workv1.ManifestWork{
ObjectMeta: metav1.ObjectMeta{
Name: mwrSet.Name,
GenerateName: mwrSet.Name + "-",
Copy link
Contributor

Choose a reason for hiding this comment

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

This generateName will generate a random hash behind right? How will we guarnatee its the namespace thats included in the MW name?

I see this logic below in the helper.go , but wondering how it ties to this change?

Copy link
Author

Choose a reason for hiding this comment

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

generateName only ensures uniqueness

Copy link
Author

Choose a reason for hiding this comment

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

and controller logic already relies on labels for lookup & deletion so thats why

Copy link
Author

Choose a reason for hiding this comment

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

The name assignment in helper.go is only used for unit tests.
@annelaucg

Copy link
Author

Choose a reason for hiding this comment

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

This generateName will generate a random hash behind right? How will we guarnatee its the namespace thats included in the MW name?

Yes — generateName lets the API server append a unique suffix to the ManifestWork name to avoid collisions

Copy link
Contributor

@annelaucg annelaucg Feb 24, 2026

Choose a reason for hiding this comment

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

Got it, so it ensures unique-ness, but we will not append the namespace to the MW name. Any concerns about human readability of the knowing which ManifestWork was from which namespace?

Signed-off-by: shivansh-source <shivanshsiddhi1234@gmail.com>
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)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (1)

866-878: ⚠️ Potential issue | 🟡 Minor

Fix misleading failure messages for placement2/placement3 counts.
These branches are checking the count, but the message says “got error” and prints len(works). This was already flagged before and still appears. Consider reporting the count (and optionally the slice) directly.

💡 Proposed fix
-	if len(works) != 1 {
-		t.Fatalf("Expected ManifestWork for placement2 to exist, but got error: %v", len(works))
-	}
+	if len(works) != 1 {
+		t.Fatalf("Expected 1 ManifestWork for placement2, got %d", len(works))
+	}
@@
-	if len(works) != 1 {
-		t.Fatalf("Expected ManifestWork for placement3 to exist, but got error: %v", len(works))
-	}
+	if len(works) != 1 {
+		t.Fatalf("Expected 1 ManifestWork for placement3, got %d", len(works))
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go`
around lines 866 - 878, The failure messages for placement2 and placement3
incorrectly say "got error" and print len(works); update the t.Fatalf calls
after the length checks in manifestworkreplicaset_deploy_test.go to report the
actual count (and optionally the slice) instead of implying an error —
specifically change the two t.Fatalf lines that follow the if len(works) != 1
checks (the block that sets currentMW2 and the block that calls listWorksByMWRS
for "place-test3") to something like "Expected 1 ManifestWork for placementX,
but got %d: %v" using len(works) and works to make the message accurate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go`:
- Around line 866-878: The failure messages for placement2 and placement3
incorrectly say "got error" and print len(works); update the t.Fatalf calls
after the length checks in manifestworkreplicaset_deploy_test.go to report the
actual count (and optionally the slice) instead of implying an error —
specifically change the two t.Fatalf lines that follow the if len(works) != 1
checks (the block that sets currentMW2 and the block that calls listWorksByMWRS
for "place-test3") to something like "Expected 1 ManifestWork for placementX,
but got %d: %v" using len(works) and works to make the message accurate.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28f3b5e and 5fce56d.

📒 Files selected for processing (1)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go

Signed-off-by: shivansh-source <shivanshsiddhi1234@gmail.com>
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.

should use generateName to create manifestwork from manifestworkreplicaset

3 participants