Skip to content

Commit 2b5829a

Browse files
committed
Implement rollout strategy
Signed-off-by: melserngawy <melserng@redhat.com>
1 parent 774e761 commit 2b5829a

File tree

3 files changed

+120
-46
lines changed

3 files changed

+120
-46
lines changed

pkg/work/helper/helpers.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"k8s.io/klog/v2"
2929

3030
clusterlister "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1"
31+
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
3132
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
3233
workapiv1 "open-cluster-management.io/api/work/v1"
3334
)
@@ -483,7 +484,15 @@ func (pdl PlacementDecisionGetter) List(selector labels.Selector, namespace stri
483484
// Get added and deleted clusters names
484485
func GetClusters(client clusterlister.PlacementDecisionLister, placement *clusterv1beta1.Placement,
485486
existingClusters sets.Set[string]) (sets.Set[string], sets.Set[string], error) {
486-
pdtracker := clusterv1beta1.NewPlacementDecisionClustersTracker(placement, PlacementDecisionGetter{Client: client}, existingClusters)
487+
existingClusterGroups := make(map[clusterv1beta1.GroupKey]sets.Set[string])
488+
pdtracker := clusterv1beta1.NewPlacementDecisionClustersTracker(placement, PlacementDecisionGetter{Client: client}, existingClusters, existingClusterGroups)
487489

488490
return pdtracker.Get()
489491
}
492+
493+
func GetRollOutHandler(client clusterlister.PlacementDecisionLister, placement *clusterv1beta1.Placement, existingClusters sets.Set[string]) (*clusterv1alpha1.RolloutHandler, error) {
494+
existingClusterGroups := make(map[clusterv1beta1.GroupKey]sets.Set[string])
495+
pdtracker := clusterv1beta1.NewPlacementDecisionClustersTracker(placement, PlacementDecisionGetter{Client: client}, existingClusters, existingClusterGroups)
496+
497+
return clusterv1alpha1.NewRolloutHandler(pdtracker)
498+
}

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ const (
3737
// TODO move this to the api repo
3838
ManifestWorkReplicaSetControllerNameLabelKey = "work.open-cluster-management.io/manifestworkreplicaset"
3939

40+
// ManifestWorkReplicaSetPlacementNameLabelKey is the label key on manifestwork to ref to the Placement that select
41+
// the managedCluster on the manifestWorkReplicaSet's PlacementRef.
42+
ManifestWorkReplicaSetPlacementNameLabelKey = "work.open-cluster-management.io/PlacementName"
43+
4044
// ManifestWorkReplicaSetFinalizer is the name of the finalizer added to ManifestWorkReplicaSet. It is used to ensure
4145
// related manifestworks is deleted
4246
ManifestWorkReplicaSetFinalizer = "work.open-cluster-management.io/manifest-work-cleanup"
@@ -180,3 +184,19 @@ func listManifestWorksByManifestWorkReplicaSet(mwrs *workapiv1alpha1.ManifestWor
180184
selector := labels.NewSelector().Add(*req)
181185
return manifestWorkLister.List(selector)
182186
}
187+
188+
func listManifestWorksByMWRSetPlacementRef(mwrs *workapiv1alpha1.ManifestWorkReplicaSet, placementName string,
189+
manifestWorkLister worklisterv1.ManifestWorkLister) ([]*workapiv1.ManifestWork, error) {
190+
reqMWRSet, err := labels.NewRequirement(ManifestWorkReplicaSetControllerNameLabelKey, selection.Equals, []string{manifestWorkReplicaSetKey(mwrs)})
191+
if err != nil {
192+
return nil, err
193+
}
194+
195+
reqPlacementRef, err := labels.NewRequirement(ManifestWorkReplicaSetPlacementNameLabelKey, selection.Equals, []string{placementName})
196+
if err != nil {
197+
return nil, err
198+
}
199+
200+
selector := labels.NewSelector().Add(*reqMWRSet, *reqPlacementRef)
201+
return manifestWorkLister.List(selector)
202+
}

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go

Lines changed: 90 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import (
1212

1313
clusterlister "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1"
1414
worklisterv1 "open-cluster-management.io/api/client/work/listers/work/v1"
15-
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
15+
//clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
16+
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
1617
"open-cluster-management.io/api/utils/work/v1/workapplier"
1718
workv1 "open-cluster-management.io/api/work/v1"
1819
workapiv1alpha1 "open-cluster-management.io/api/work/v1alpha1"
@@ -31,8 +32,17 @@ type deployReconciler struct {
3132
func (d *deployReconciler) reconcile(ctx context.Context, mwrSet *workapiv1alpha1.ManifestWorkReplicaSet,
3233
) (*workapiv1alpha1.ManifestWorkReplicaSet, reconcileState, error) {
3334
// Manifestwork create/update/delete logic.
34-
var placements []*clusterv1beta1.Placement
35+
36+
//var placements []*clusterv1beta1.Placement
37+
//existingClusters := make(map[string]sets.String)
38+
// placementName as key and RolloutResult is the value
39+
//placementsRolloutResults := make(map[string]clusterv1alpha1.RolloutResult)
40+
var errs []error
41+
count := 0
42+
43+
// Getting the placements and the created ManifestWorks related to each placement
3544
for _, placementRef := range mwrSet.Spec.PlacementRefs {
45+
existingClusters, addedClusters, deletedClusters := sets.New[string](), sets.New[string](), sets.New[string]()
3646
placement, err := d.placementLister.Placements(mwrSet.Namespace).Get(placementRef.Name)
3747
if errors.IsNotFound(err) {
3848
apimeta.SetStatusCondition(&mwrSet.Status.Conditions, GetPlacementDecisionVerified(workapiv1alpha1.ReasonPlacementDecisionNotFound, ""))
@@ -41,74 +51,101 @@ func (d *deployReconciler) reconcile(ctx context.Context, mwrSet *workapiv1alpha
4151
if err != nil {
4252
return mwrSet, reconcileContinue, fmt.Errorf("failed get placement %w", err)
4353
}
44-
placements = append(placements, placement)
45-
}
4654

47-
manifestWorks, err := listManifestWorksByManifestWorkReplicaSet(mwrSet, d.manifestWorkLister)
48-
if err != nil {
49-
return mwrSet, reconcileContinue, err
50-
}
55+
//placements = append(placements, placement)
56+
manifestWorks, err := listManifestWorksByMWRSetPlacementRef(mwrSet, placementRef.Name, d.manifestWorkLister)
57+
if err != nil {
58+
return mwrSet, reconcileContinue, err
59+
}
5160

52-
var errs []error
53-
addedClusters, deletedClusters, existingClusters := sets.New[string](), sets.New[string](), sets.New[string]()
54-
for _, mw := range manifestWorks {
55-
existingClusters.Insert(mw.Namespace)
56-
}
61+
for _, mw := range manifestWorks {
62+
existingClusters.Insert(mw.Namespace)
63+
}
5764

58-
for _, placement := range placements {
59-
added, deleted, err := helper.GetClusters(d.placeDecisionLister, placement, existingClusters)
65+
rolloutHandler, err := helper.GetRollOutHandler(d.placeDecisionLister, placement, existingClusters)
6066
if err != nil {
6167
apimeta.SetStatusCondition(&mwrSet.Status.Conditions, GetPlacementDecisionVerified(workapiv1alpha1.ReasonNotAsExpected, ""))
6268

6369
return mwrSet, reconcileContinue, utilerrors.NewAggregate(errs)
6470
}
6571

66-
addedClusters = addedClusters.Union(added)
67-
deletedClusters = deletedClusters.Union(deleted)
68-
}
69-
70-
// Create manifestWork for added clusters
71-
for cls := range addedClusters {
72-
mw, err := CreateManifestWork(mwrSet, cls)
73-
if err != nil {
74-
errs = append(errs, err)
75-
continue
72+
// The clusterRolloutStatusFunc need different signature only clusterName as input param not helping
73+
_, rolloutResult, err := rolloutHandler.GetRolloutCluster(placementRef.RolloutStrategy, d.clusterRolloutStatusFunc)
74+
//placementsRolloutResults[placementRef.Name] = rolloutResult
75+
76+
// Creating ManifestWork that has the ToApply status
77+
for cls, rolloutStatue := range rolloutResult.ClustersToRollout {
78+
if rolloutStatue.Status == clusterv1alpha1.ToApply {
79+
mw, err := CreateManifestWork(mwrSet, cls, placementRef.Name)
80+
if err != nil {
81+
errs = append(errs, err)
82+
continue
83+
}
84+
85+
_, err = d.workApplier.Apply(ctx, mw)
86+
if err != nil {
87+
errs = append(errs, err)
88+
}
89+
}
7690
}
7791

78-
_, err = d.workApplier.Apply(ctx, mw)
92+
// checking the Added and deleted clusters.
93+
// How to check if the added cluster is part of the rolloutResult ?
94+
// Does the RolloutResult already consider the added clusters ?
95+
// Better to have the deleted/added clusters within the rolloutResult
96+
addedClusters, deletedClusters, err = helper.GetClusters(d.placeDecisionLister, placement, existingClusters)
7997
if err != nil {
80-
errs = append(errs, err)
98+
apimeta.SetStatusCondition(&mwrSet.Status.Conditions, GetPlacementDecisionVerified(workapiv1alpha1.ReasonNotAsExpected, ""))
99+
100+
return mwrSet, reconcileContinue, utilerrors.NewAggregate(errs)
81101
}
82-
}
83102

84-
// Update manifestWorks in case there are changes at ManifestWork or ManifestWorkReplicaSet
85-
for cls := range existingClusters {
86-
// Delete manifestWork for deleted clusters
87-
if deletedClusters.Has(cls) {
88-
err = d.workApplier.Delete(ctx, cls, mwrSet.Name)
103+
// Create manifestWork for added clusters
104+
for cls := range addedClusters {
105+
mw, err := CreateManifestWork(mwrSet, cls, placementRef.Name)
89106
if err != nil {
90107
errs = append(errs, err)
108+
continue
91109
}
92-
continue
93-
}
94110

95-
mw, err := CreateManifestWork(mwrSet, cls)
96-
if err != nil {
97-
errs = append(errs, err)
98-
continue
111+
_, err = d.workApplier.Apply(ctx, mw)
112+
if err != nil {
113+
errs = append(errs, err)
114+
}
99115
}
100116

101-
_, err = d.workApplier.Apply(ctx, mw)
102-
if err != nil {
103-
errs = append(errs, err)
117+
// How to rollOut updated manifestWork ? that can be handled in the clusterRolloutStatusFunc
118+
// Update manifestWorks in case there are changes at ManifestWork or ManifestWorkReplicaSet
119+
for cls := range existingClusters {
120+
// Delete manifestWork for deleted clusters
121+
if deletedClusters.Has(cls) {
122+
err = d.workApplier.Delete(ctx, cls, mwrSet.Name)
123+
if err != nil {
124+
errs = append(errs, err)
125+
}
126+
continue
127+
}
128+
129+
mw, err := CreateManifestWork(mwrSet, cls, placementRef.Name)
130+
if err != nil {
131+
errs = append(errs, err)
132+
continue
133+
}
134+
135+
_, err = d.workApplier.Apply(ctx, mw)
136+
if err != nil {
137+
errs = append(errs, err)
138+
}
104139
}
140+
count = count + len(rolloutResult.ClustersToRollout)
105141
}
106142

107143
// Set the Summary
108144
if mwrSet.Status.Summary == (workapiv1alpha1.ManifestWorkReplicaSetSummary{}) {
109145
mwrSet.Status.Summary = workapiv1alpha1.ManifestWorkReplicaSetSummary{}
110146
}
111-
total := len(existingClusters) - len(deletedClusters) + len(addedClusters)
147+
//total := len(existingClusters) - len(deletedClusters) + len(addedClusters)
148+
total := count
112149
if total < 0 {
113150
total = 0
114151
}
@@ -127,6 +164,13 @@ func (d *deployReconciler) reconcile(ctx context.Context, mwrSet *workapiv1alpha
127164
return mwrSet, reconcileContinue, utilerrors.NewAggregate(errs)
128165
}
129166

167+
// TODO: Implement clusterRolloutStatusFunc logic.
168+
func (d *deployReconciler) clusterRolloutStatusFunc(clusterName string) clusterv1alpha1.ClusterRolloutStatus {
169+
clsRolloutStatus := clusterv1alpha1.ClusterRolloutStatus{}
170+
171+
return clsRolloutStatus
172+
}
173+
130174
// GetManifestworkApplied return only True status if there all clusters have manifests applied as expected
131175
func GetManifestworkApplied(reason string, message string) metav1.Condition {
132176
if reason == workapiv1alpha1.ReasonAsExpected {
@@ -156,7 +200,7 @@ func getCondition(conditionType string, reason string, message string, status me
156200
}
157201
}
158202

159-
func CreateManifestWork(mwrSet *workapiv1alpha1.ManifestWorkReplicaSet, clusterNS string) (*workv1.ManifestWork, error) {
203+
func CreateManifestWork(mwrSet *workapiv1alpha1.ManifestWorkReplicaSet, clusterNS string, placementRefName string) (*workv1.ManifestWork, error) {
160204
if clusterNS == "" {
161205
return nil, fmt.Errorf("invalid cluster namespace")
162206
}
@@ -165,7 +209,8 @@ func CreateManifestWork(mwrSet *workapiv1alpha1.ManifestWorkReplicaSet, clusterN
165209
ObjectMeta: metav1.ObjectMeta{
166210
Name: mwrSet.Name,
167211
Namespace: clusterNS,
168-
Labels: map[string]string{ManifestWorkReplicaSetControllerNameLabelKey: manifestWorkReplicaSetKey(mwrSet)},
212+
Labels: map[string]string{ManifestWorkReplicaSetControllerNameLabelKey: manifestWorkReplicaSetKey(mwrSet),
213+
ManifestWorkReplicaSetPlacementNameLabelKey: placementRefName},
169214
},
170215
Spec: mwrSet.Spec.ManifestWorkTemplate}, nil
171216
}

0 commit comments

Comments
 (0)