Skip to content

Commit 755965a

Browse files
author
Arvind Thirumurugan
committed
update validatePlacement function
Signed-off-by: Arvind Thirumurugan <[email protected]>
1 parent 1f4fe5d commit 755965a

File tree

8 files changed

+64
-34
lines changed

8 files changed

+64
-34
lines changed

pkg/controllers/placement/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, key controller.QueueKey) (ct
7272
klog.V(2).InfoS("Placement reconciliation ends", "placementKey", placementKey, "latency", latency)
7373
}()
7474

75-
placementObj, err := controller.FetchPlacementFromKey(ctx, r.Client, queue.PlacementKey(placementKey))
75+
placementObj, err := controller.FetchPlacementFromQueueKey(ctx, r.Client, queue.PlacementKey(placementKey))
7676
if err != nil {
7777
if apierrors.IsNotFound(err) {
7878
klog.V(4).InfoS("Ignoring NotFound placement", "placementKey", placementKey)

pkg/controllers/rollout/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req runtime.Request) (runtim
7272
}()
7373

7474
// Get the placement object (either ClusterResourcePlacement or ResourcePlacement)
75-
placementObj, err := controller.FetchPlacementFromKey(ctx, r.Client, controller.GetObjectKeyFromRequest(req))
75+
placementObj, err := controller.FetchPlacementFromQueueKey(ctx, r.Client, controller.GetObjectKeyFromRequest(req))
7676
if err != nil {
7777
if errors.IsNotFound(err) {
7878
klog.V(4).InfoS("Ignoring NotFound placement", "placementKey", placementKey)

pkg/controllers/updaterun/initialization.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
apierrors "k8s.io/apimachinery/pkg/api/errors"
2828
"k8s.io/apimachinery/pkg/api/meta"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"k8s.io/apimachinery/pkg/types"
3031
"k8s.io/klog/v2"
3132
"sigs.k8s.io/controller-runtime/pkg/client"
3233

@@ -44,8 +45,8 @@ func (r *Reconciler) initialize(
4445
ctx context.Context,
4546
updateRun *placementv1beta1.ClusterStagedUpdateRun,
4647
) ([]*placementv1beta1.ClusterResourceBinding, []*placementv1beta1.ClusterResourceBinding, error) {
47-
// Validate the ClusterResourcePlace object referenced by the ClusterStagedUpdateRun.
48-
placementName, err := r.validateCRP(ctx, updateRun)
48+
// Validate the Placement object referenced by the StagedUpdateRun.
49+
placementName, err := r.validatePlacement(ctx, updateRun)
4950
if err != nil {
5051
return nil, nil, err
5152
}
@@ -71,29 +72,48 @@ func (r *Reconciler) initialize(
7172
return scheduledBindings, toBeDeletedBindings, r.recordInitializationSucceeded(ctx, updateRun)
7273
}
7374

74-
// validateCRP validates the ClusterResourcePlacement object referenced by the ClusterStagedUpdateRun.
75-
func (r *Reconciler) validateCRP(ctx context.Context, updateRun *placementv1beta1.ClusterStagedUpdateRun) (string, error) {
75+
// validatePlacement validates the Placement object (CRP or RP) referenced by the StagedUpdateRun.
76+
func (r *Reconciler) validatePlacement(ctx context.Context, updateRun placementv1beta1.StagedUpdateRunObj) (string, error) {
7677
updateRunRef := klog.KObj(updateRun)
77-
// Fetch the ClusterResourcePlacement object.
78-
placementName := updateRun.Spec.PlacementName
79-
var crp placementv1beta1.ClusterResourcePlacement
80-
if err := r.Client.Get(ctx, client.ObjectKey{Name: placementName}, &crp); err != nil {
81-
klog.ErrorS(err, "Failed to get ClusterResourcePlacement", "clusterResourcePlacement", placementName, "clusterStagedUpdateRun", updateRunRef)
78+
79+
// Get placement name from the updateRun spec using interface methods
80+
placementName := updateRun.GetStagedUpdateRunSpec().PlacementName
81+
82+
// Create NamespacedName for the placement
83+
// For ClusterStagedUpdateRun, namespace will be empty (cluster-scoped)
84+
// For StagedUpdateRun, namespace will be the actual namespace (namespace-scoped)
85+
namespacedName := types.NamespacedName{
86+
Name: placementName,
87+
Namespace: updateRun.GetNamespace(),
88+
}
89+
90+
// Fetch the placement object using the utility function
91+
// This automatically determines whether to fetch CRP or RP based on namespace presence
92+
placement, err := controller.FetchPlacementFromNamespacedName(ctx, r.Client, namespacedName)
93+
if err != nil {
8294
if apierrors.IsNotFound(err) {
83-
// we won't continue or retry the initialization if the ClusterResourcePlacement is not found.
84-
crpNotFoundErr := controller.NewUserError(fmt.Errorf("parent clusterResourcePlacement not found"))
85-
return "", fmt.Errorf("%w: %s", errInitializedFailed, crpNotFoundErr.Error())
95+
placementNotFoundErr := controller.NewUserError(fmt.Errorf("parent placement not found"))
96+
klog.ErrorS(err, "Failed to get placement", "placement", placementName, "namespace", updateRun.GetNamespace(), "stagedUpdateRun", updateRunRef)
97+
return "", fmt.Errorf("%w: %s", errInitializedFailed, placementNotFoundErr.Error())
8698
}
99+
klog.ErrorS(err, "Failed to get placement", "placement", placementName, "namespace", updateRun.GetNamespace(), "stagedUpdateRun", updateRunRef)
87100
return "", controller.NewAPIServerError(true, err)
88101
}
89-
// Check if the ClusterResourcePlacement has an external rollout strategy.
90-
if crp.Spec.Strategy.Type != placementv1beta1.ExternalRolloutStrategyType {
91-
klog.V(2).InfoS("The clusterResourcePlacement does not have an external rollout strategy", "clusterResourcePlacement", placementName, "clusterStagedUpdateRun", updateRunRef)
92-
wrongRolloutTypeErr := controller.NewUserError(errors.New("parent clusterResourcePlacement does not have an external rollout strategy, current strategy: " + string(crp.Spec.Strategy.Type)))
102+
103+
// Check if the Placement has an external rollout strategy using interface methods
104+
placementSpec := placement.GetPlacementSpec()
105+
if placementSpec.Strategy.Type != placementv1beta1.ExternalRolloutStrategyType {
106+
klog.V(2).InfoS("The placement does not have an external rollout strategy", "placement", placementName, "namespace", updateRun.GetNamespace(), "stagedUpdateRun", updateRunRef)
107+
wrongRolloutTypeErr := controller.NewUserError(errors.New("parent placement does not have an external rollout strategy, current strategy: " + string(placementSpec.Strategy.Type)))
93108
return "", fmt.Errorf("%w: %s", errInitializedFailed, wrongRolloutTypeErr.Error())
94109
}
95-
updateRun.Status.ApplyStrategy = crp.Spec.Strategy.ApplyStrategy
96-
return crp.Name, nil
110+
111+
// Update the apply strategy in the updateRun status using interface methods
112+
updateRunStatus := updateRun.GetStagedUpdateRunStatus()
113+
updateRunStatus.ApplyStrategy = placementSpec.Strategy.ApplyStrategy
114+
updateRun.SetStagedUpdateRunStatus(*updateRunStatus)
115+
116+
return placementName, nil
97117
}
98118

99119
// determinePolicySnapshot retrieves the latest policy snapshot associated with the ClusterResourcePlacement,

pkg/controllers/updaterun/validation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (r *Reconciler) validate(
4444
klog.V(2).InfoS("Start to validate the clusterStagedUpdateRun", "clusterStagedUpdateRun", updateRunRef)
4545

4646
// Validate the ClusterResourcePlacement object referenced by the ClusterStagedUpdateRun.
47-
placementName, err := r.validateCRP(ctx, updateRunCopy)
47+
placementName, err := r.validatePlacement(ctx, updateRunCopy)
4848
if err != nil {
4949
return -1, nil, nil, err
5050
}

pkg/scheduler/scheduler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func (s *Scheduler) scheduleOnce(ctx context.Context, worker int) {
134134
}()
135135

136136
// Retrieve the placement object (either ClusterResourcePlacement or ResourcePlacement).
137-
placement, err := controller.FetchPlacementFromKey(ctx, s.client, placementKey)
137+
placement, err := controller.FetchPlacementFromQueueKey(ctx, s.client, placementKey)
138138
if err != nil {
139139
if apiErrors.IsNotFound(err) {
140140
// The placement has been gone before the scheduler gets a chance to

pkg/scheduler/watchers/placement/watcher.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
5555

5656
// Retrieve the placement object (either ClusterResourcePlacement or ResourcePlacement).
5757
placementKey := controller.GetObjectKeyFromRequest(req)
58-
placement, err := controller.FetchPlacementFromKey(ctx, r.Client, placementKey)
58+
placement, err := controller.FetchPlacementFromQueueKey(ctx, r.Client, placementKey)
5959
if err != nil {
6060
klog.ErrorS(err, "Failed to get placement", "placement", placementRef)
6161
return ctrl.Result{}, controller.NewAPIServerError(true, client.IgnoreNotFound(err))

pkg/utils/controller/placement_resolver.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,29 @@ const (
3535
namespaceSeparator = "/"
3636
)
3737

38-
// FetchPlacementFromKey resolves a PlacementKey to a concrete placement object that implements PlacementObj.
39-
func FetchPlacementFromKey(ctx context.Context, c client.Reader, placementKey queue.PlacementKey) (fleetv1beta1.PlacementObj, error) {
38+
// FetchPlacementFromQueueKey resolves a Queue PlacementKey to a concrete placement object that implements PlacementObj.
39+
func FetchPlacementFromQueueKey(ctx context.Context, c client.Reader, placementKey queue.PlacementKey) (fleetv1beta1.PlacementObj, error) {
4040
// Extract namespace and name from the placement key
4141
namespace, name, err := ExtractNamespaceNameFromKey(placementKey)
4242
if err != nil {
4343
return nil, err
4444
}
45+
return FetchPlacementFromNamespacedName(ctx, c, types.NamespacedName{Namespace: namespace, Name: name})
46+
}
47+
48+
// FetchPlacementFromNamespacedName resolves a NamespacedName to a concrete placement object that implements PlacementObj.
49+
func FetchPlacementFromNamespacedName(ctx context.Context, c client.Reader, nn types.NamespacedName) (fleetv1beta1.PlacementObj, error) {
4550
// Check if the key contains a namespace separator
4651
var placement fleetv1beta1.PlacementObj
47-
if namespace != "" {
52+
if nn.Namespace != "" {
4853
// This is a namespaced ResourcePlacement
4954
placement = &fleetv1beta1.ResourcePlacement{}
5055
} else {
5156
// This is a cluster-scoped ClusterResourcePlacement
5257
placement = &fleetv1beta1.ClusterResourcePlacement{}
5358
}
54-
key := types.NamespacedName{
55-
Namespace: namespace,
56-
Name: name,
57-
}
58-
if err := c.Get(ctx, key, placement); err != nil {
59+
60+
if err := c.Get(ctx, nn, placement); err != nil {
5961
return nil, err
6062
}
6163
return placement, nil
@@ -94,6 +96,14 @@ func GetObjectKeyFromNamespaceName(namespace, name string) string {
9496
}
9597
}
9698

99+
// GetNamespacedNameFromObject generates a NamespacedName from a meta object.
100+
func GetNamespacedNameFromObject(obj metav1.Object) types.NamespacedName {
101+
return types.NamespacedName{
102+
Namespace: obj.GetNamespace(),
103+
Name: obj.GetName(),
104+
}
105+
}
106+
97107
// ExtractNamespaceNameFromKey resolves a PlacementKey to a (namespace, name) tuple of the placement object.
98108
func ExtractNamespaceNameFromKey(key queue.PlacementKey) (string, string, error) {
99109
return ExtractNamespaceNameFromKeyStr(string(key))

pkg/utils/controller/placement_resolver_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import (
3232
"github.com/kubefleet-dev/kubefleet/pkg/scheduler/queue"
3333
)
3434

35-
func TestFetchPlacementFromKey(t *testing.T) {
35+
func TestFetchPlacementFromQueueKey(t *testing.T) {
3636
scheme := runtime.NewScheme()
3737
if err := fleetv1beta1.AddToScheme(scheme); err != nil {
3838
t.Fatalf("Failed to add scheme: %v", err)
@@ -302,7 +302,7 @@ func TestFetchPlacementFromKey(t *testing.T) {
302302
WithObjects(tt.objects...).
303303
Build()
304304

305-
placement, err := FetchPlacementFromKey(context.Background(), fakeClient, tt.placementKey)
305+
placement, err := FetchPlacementFromQueueKey(context.Background(), fakeClient, tt.placementKey)
306306

307307
if tt.wantErr {
308308
if err == nil {
@@ -329,7 +329,7 @@ func TestFetchPlacementFromKey(t *testing.T) {
329329
// Ignore resource version field for consistent comparison
330330
if diff := cmp.Diff(placement, tt.wantPlacement,
331331
cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion")); diff != "" {
332-
t.Errorf("FetchPlacementFromKey() diff (-got +want):\n%s", diff)
332+
t.Errorf("FetchPlacementFromQueueKey() diff (-got +want):\n%s", diff)
333333
}
334334

335335
// Verify the concrete type matches expected

0 commit comments

Comments
 (0)