Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,11 @@ func (d *deployReconciler) reconcile(ctx context.Context, mwrSet *workapiv1alpha

for _, cls := range rolloutResult.ClustersRemoved {
// Delete manifestWork for removed clusters
err = d.workApplier.Delete(ctx, cls.ClusterName, mwrSet.Name)
if err != nil {
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
}
Expand Down Expand Up @@ -381,7 +384,7 @@ func CreateManifestWork(

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?

Namespace: clusterNS,
Labels: mergedLabels,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import (
"errors"
"testing"
"time"
"fmt"


"github.com/stretchr/testify/assert"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/labels"

fakeclusterclient "open-cluster-management.io/api/client/cluster/clientset/versioned/fake"
clusterinformers "open-cluster-management.io/api/client/cluster/informers/externalversions"
fakeworkclient "open-cluster-management.io/api/client/work/clientset/versioned/fake"
workclient "open-cluster-management.io/api/client/work/clientset/versioned"
workinformers "open-cluster-management.io/api/client/work/informers/externalversions"
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
workapiv1 "open-cluster-management.io/api/work/v1"
Expand Down Expand Up @@ -761,20 +765,20 @@ func TestDeployReconcileDeletesOrphanedManifestWorks(t *testing.T) {
}

// Verify that the ManifestWork from the old placement (place-test1) was deleted
deletedMW, err := fWorkClient.WorkV1().ManifestWorks("cls1").Get(context.TODO(), mwrSet.Name, metav1.GetOptions{})
if err == nil {
t.Fatalf("Expected ManifestWork for old placement to be deleted, but it still exists: %v", deletedMW)
}

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
currentMW, err := fWorkClient.WorkV1().ManifestWorks("cls2").Get(context.TODO(), mwrSet.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("Expected ManifestWork for current placement to exist, but got error: %v", err)
}
if currentMW == nil {
t.Fatal("Expected ManifestWork for current placement to exist, but it is nil")
}

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, works: %v", len(works), works)
}
currentMW := works[0]
// Verify the placement label is correct
if currentMW.Labels[workapiv1alpha1.ManifestWorkReplicaSetPlacementNameLabelKey] != "place-test2" {
t.Fatalf("Expected placement label to be 'place-test2', got '%s'",
Expand Down Expand Up @@ -846,23 +850,34 @@ func TestDeployReconcileWithMultiplePlacementChanges(t *testing.T) {
}

// Verify that the ManifestWork from the old placement (place-test1) was deleted
_, err = fWorkClient.WorkV1().ManifestWorks("cls1").Get(context.TODO(), mwrSet.Name, metav1.GetOptions{})
if err == nil {
t.Fatal("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 ManifestWorks for old placement to be deleted, found %d", len(works))
}

// Verify that ManifestWorks from current placements (place-test2 and place-test3) still exist
currentMW2, err := fWorkClient.WorkV1().ManifestWorks("cls2").Get(context.TODO(), mwrSet.Name, metav1.GetOptions{})
works, err = listWorksByMWRS(context.TODO(), fWorkClient, "cls2", mwrSet.Namespace, mwrSet.Name, "place-test2")
if err != nil {
t.Fatalf("Expected ManifestWork for placement2 to exist, but got error: %v", err)
t.Fatal(err)
}
if len(works) != 1 {
t.Fatalf("Expected ManifestWork for placement2 to exist, but got error: %d, works: %v", len(works), works)
}
currentMW2 := works[0]
assert.Equal(t, currentMW2.Labels[workapiv1alpha1.ManifestWorkReplicaSetPlacementNameLabelKey], "place-test2")

currentMW3, err := fWorkClient.WorkV1().ManifestWorks("cls3").Get(context.TODO(), mwrSet.Name, metav1.GetOptions{})
works, err = listWorksByMWRS(context.TODO(), fWorkClient, "cls3", mwrSet.Namespace, mwrSet.Name, "place-test3")
if err != nil {
t.Fatalf("Expected ManifestWork for placement3 to exist, but got error: %v", err)
}
assert.Equal(t, currentMW3.Labels[workapiv1alpha1.ManifestWorkReplicaSetPlacementNameLabelKey], "place-test3")
if len(works) != 1 {
t.Fatalf("Expected ManifestWork for placement3 to exist, but got error: %d, works: %v", len(works), works)
}
currentMW3 := works[0]
assert.Equal(t,currentMW3.Labels[workapiv1alpha1.ManifestWorkReplicaSetPlacementNameLabelKey], "place-test3")
}
func TestDeployRolloutProgressingWhenNotAllSucceeded(t *testing.T) {
// Test case where all ManifestWorks are created (count = total) but not all have succeeded
Expand Down Expand Up @@ -1375,6 +1390,32 @@ func TestClusterRolloutStatusFunc(t *testing.T) {
})
}
}
func listWorksByMWRS(
ctx context.Context,
client workclient.Interface,
cluster string,
mwrNamespace string,
mwrName string,
placement string,
) ([]workapiv1.ManifestWork, error) {

selector := labels.Set{
workapiv1alpha1.ManifestWorkReplicaSetControllerNameLabelKey:
fmt.Sprintf("%s.%s", mwrNamespace, mwrName),
workapiv1alpha1.ManifestWorkReplicaSetPlacementNameLabelKey:
placement,
}.AsSelector().String()

list, err := client.WorkV1().
ManifestWorks(cluster).
List(ctx, metav1.ListOptions{LabelSelector: selector})

if err != nil {
return nil, err
}

return list.Items, nil
}

func TestShouldReturnToApply(t *testing.T) {
now := metav1.Now()
Expand Down
4 changes: 2 additions & 2 deletions pkg/work/hub/test/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func CreateTestManifestWorks(name, namespace string, placementName string, clust
var works []runtime.Object
for _, c := range clusters {
mw, _ := spoketesting.NewManifestWork(0, obj)
mw.Name = name
mw.Name = fmt.Sprintf("%s-%s", name, c)
mw.Namespace = c
mw.Labels = map[string]string{
"work.open-cluster-management.io/manifestworkreplicaset": fmt.Sprintf("%s.%s", namespace, name),
Expand All @@ -90,7 +90,7 @@ func CreateTestManifestWorks(name, namespace string, placementName string, clust
func CreateTestManifestWork(name, namespace string, placementName string, clusterName string) *workapiv1.ManifestWork {
obj := testingcommon.NewUnstructured("v1", "kind", "test-ns", "test-name")
mw, _ := spoketesting.NewManifestWork(0, obj)
mw.Name = name
mw.Name = fmt.Sprintf("%s-%s", name, clusterName)
mw.Namespace = clusterName
mw.Labels = map[string]string{
"work.open-cluster-management.io/manifestworkreplicaset": fmt.Sprintf("%s.%s", namespace, name),
Expand Down
Loading