in pkg/controllers/clusterresourceplacement/controller.go [265:351]
func (r *Reconciler) getOrCreateClusterSchedulingPolicySnapshot(ctx context.Context, crp *fleetv1beta1.ClusterResourcePlacement, revisionHistoryLimit int) (*fleetv1beta1.ClusterSchedulingPolicySnapshot, error) {
crpKObj := klog.KObj(crp)
schedulingPolicy := crp.Spec.Policy.DeepCopy()
if schedulingPolicy != nil {
schedulingPolicy.NumberOfClusters = nil // will exclude the numberOfClusters
}
policyHash, err := resource.HashOf(schedulingPolicy)
if err != nil {
klog.ErrorS(err, "Failed to generate policy hash of crp", "clusterResourcePlacement", crpKObj)
return nil, controller.NewUnexpectedBehaviorError(err)
}
// latestPolicySnapshotIndex should be -1 when there is no snapshot.
latestPolicySnapshot, latestPolicySnapshotIndex, err := r.lookupLatestClusterSchedulingPolicySnapshot(ctx, crp)
if err != nil {
return nil, err
}
if latestPolicySnapshot != nil && string(latestPolicySnapshot.Spec.PolicyHash) == policyHash {
if err := r.ensureLatestPolicySnapshot(ctx, crp, latestPolicySnapshot); err != nil {
return nil, err
}
klog.V(2).InfoS("Policy has not been changed and updated the existing clusterSchedulingPolicySnapshot", "clusterResourcePlacement", crpKObj, "clusterSchedulingPolicySnapshot", klog.KObj(latestPolicySnapshot))
return latestPolicySnapshot, nil
}
// Need to create new snapshot when 1) there is no snapshots or 2) the latest snapshot hash != current one.
// mark the last policy snapshot as inactive if it is different from what we have now
if latestPolicySnapshot != nil &&
string(latestPolicySnapshot.Spec.PolicyHash) != policyHash &&
latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] == strconv.FormatBool(true) {
// set the latest label to false first to make sure there is only one or none active policy snapshot
latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] = strconv.FormatBool(false)
if err := r.Client.Update(ctx, latestPolicySnapshot); err != nil {
klog.ErrorS(err, "Failed to set the isLatestSnapshot label to false", "clusterResourcePlacement", crpKObj, "clusterSchedulingPolicySnapshot", klog.KObj(latestPolicySnapshot))
return nil, controller.NewUpdateIgnoreConflictError(err)
}
klog.V(2).InfoS("Marked the existing clusterSchedulingPolicySnapshot as inactive", "clusterResourcePlacement", crpKObj, "clusterSchedulingPolicySnapshot", klog.KObj(latestPolicySnapshot))
}
// delete redundant snapshot revisions before creating a new snapshot to guarantee that the number of snapshots
// won't exceed the limit.
if err := r.deleteRedundantSchedulingPolicySnapshots(ctx, crp, revisionHistoryLimit); err != nil {
return nil, err
}
// create a new policy snapshot
latestPolicySnapshotIndex++
latestPolicySnapshot = &fleetv1beta1.ClusterSchedulingPolicySnapshot{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, crp.Name, latestPolicySnapshotIndex),
Labels: map[string]string{
fleetv1beta1.CRPTrackingLabel: crp.Name,
fleetv1beta1.IsLatestSnapshotLabel: strconv.FormatBool(true),
fleetv1beta1.PolicyIndexLabel: strconv.Itoa(latestPolicySnapshotIndex),
},
Annotations: map[string]string{
fleetv1beta1.CRPGenerationAnnotation: strconv.FormatInt(crp.Generation, 10),
},
},
Spec: fleetv1beta1.SchedulingPolicySnapshotSpec{
Policy: schedulingPolicy,
PolicyHash: []byte(policyHash),
},
}
policySnapshotKObj := klog.KObj(latestPolicySnapshot)
if err := controllerutil.SetControllerReference(crp, latestPolicySnapshot, r.Scheme); err != nil {
klog.ErrorS(err, "Failed to set owner reference", "clusterSchedulingPolicySnapshot", policySnapshotKObj)
// should never happen
return nil, controller.NewUnexpectedBehaviorError(err)
}
// make sure each policySnapshot should always have the annotation if CRP is selectN type
if crp.Spec.Policy != nil &&
crp.Spec.Policy.PlacementType == fleetv1beta1.PickNPlacementType &&
crp.Spec.Policy.NumberOfClusters != nil {
// Note that all policy snapshots should have the CRP generation annotation set already,
// so the Annotations field will not be nil.
latestPolicySnapshot.Annotations[fleetv1beta1.NumberOfClustersAnnotation] = strconv.Itoa(int(*crp.Spec.Policy.NumberOfClusters))
}
if err := r.Client.Create(ctx, latestPolicySnapshot); err != nil {
klog.ErrorS(err, "Failed to create new clusterSchedulingPolicySnapshot", "clusterSchedulingPolicySnapshot", policySnapshotKObj)
return nil, controller.NewAPIServerError(false, err)
}
klog.V(2).InfoS("Created new clusterSchedulingPolicySnapshot", "clusterResourcePlacement", crpKObj, "clusterSchedulingPolicySnapshot", policySnapshotKObj)
return latestPolicySnapshot, nil
}