Skip to content

Commit af5a423

Browse files
Add clusterClass generation check to Cluster reconciler
1 parent ad074ef commit af5a423

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

internal/controllers/topology/cluster/cluster_controller.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
kerrors "k8s.io/apimachinery/pkg/util/errors"
2828
"k8s.io/apimachinery/pkg/util/validation/field"
2929
"k8s.io/client-go/tools/record"
30+
"k8s.io/klog/v2"
3031
ctrl "sigs.k8s.io/controller-runtime"
3132
"sigs.k8s.io/controller-runtime/pkg/builder"
3233
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -175,26 +176,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
175176
return ctrl.Result{}, err
176177
}
177178

178-
// Get ClusterClass.
179-
clusterClass := &clusterv1.ClusterClass{}
180-
key := client.ObjectKey{Name: cluster.Spec.Topology.Class, Namespace: cluster.Namespace}
181-
if err := r.Client.Get(ctx, key, clusterClass); err != nil {
182-
return ctrl.Result{}, errors.Wrapf(err, "failed to retrieve ClusterClass %s", cluster.Spec.Topology.Class)
183-
}
184-
// Default and Validate the Cluster based on information from the ClusterClass.
185-
// This step is needed as if the ClusterClass does not exist at Cluster creation some fields may not be defaulted or
186-
// validated in the webhook.
187-
if errs := webhooks.DefaultVariables(cluster, clusterClass); len(errs) > 0 {
188-
return ctrl.Result{}, apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), cluster.Name, errs)
189-
}
190-
if errs := webhooks.ValidateClusterForClusterClass(cluster, clusterClass, field.NewPath("spec", "topology")); len(errs) > 0 {
191-
return ctrl.Result{}, apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), cluster.Name, errs)
192-
}
193-
194179
// Create a scope initialized with only the cluster; during reconcile
195180
// additional information will be added about the Cluster blueprint, current state and desired state.
196181
s := scope.New(cluster)
197-
s.Blueprint.ClusterClass = clusterClass
198182

199183
defer func() {
200184
if err := r.reconcileConditions(s, cluster, reterr); err != nil {
@@ -221,6 +205,30 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
221205
func (r *Reconciler) reconcile(ctx context.Context, s *scope.Scope) (ctrl.Result, error) {
222206
var err error
223207

208+
log := klog.FromContext(ctx)
209+
// Get ClusterClass.
210+
clusterClass := &clusterv1.ClusterClass{}
211+
key := client.ObjectKey{Name: s.Current.Cluster.Spec.Topology.Class, Namespace: s.Current.Cluster.Namespace}
212+
if err := r.Client.Get(ctx, key, clusterClass); err != nil {
213+
return ctrl.Result{}, errors.Wrapf(err, "failed to retrieve ClusterClass %s", s.Current.Cluster.Spec.Topology.Class)
214+
}
215+
216+
s.Blueprint.ClusterClass = clusterClass
217+
// If the ClusterClass `metadata.Generation` doesn't match the `status.ObservedGeneration` requeue as the ClusterClass
218+
// is not up to date.
219+
if clusterClass.GetGeneration() != clusterClass.Status.ObservedGeneration {
220+
return ctrl.Result{}, errors.New(fmt.Sprintf("ClusterClass %s not up to date. Requeuing", "ClusterClass", clusterClass.Name))
221+
}
222+
223+
// Default and Validate the Cluster based on information from the ClusterClass.
224+
// This step is needed as if the ClusterClass does not exist at Cluster creation some fields may not be defaulted or
225+
// validated in the webhook.
226+
if errs := webhooks.DefaultVariables(s.Current.Cluster, clusterClass); len(errs) > 0 {
227+
return ctrl.Result{}, apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), s.Current.Cluster.Name, errs)
228+
}
229+
if errs := webhooks.ValidateClusterForClusterClass(s.Current.Cluster, clusterClass, field.NewPath("spec", "topology")); len(errs) > 0 {
230+
return ctrl.Result{}, apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Cluster").GroupKind(), s.Current.Cluster.Name, errs)
231+
}
224232
// Gets the blueprint with the ClusterClass and the referenced templates
225233
// and store it in the request scope.
226234
s.Blueprint, err = r.getBlueprint(ctx, s.Current.Cluster, s.Blueprint.ClusterClass)

0 commit comments

Comments
 (0)