func()

in pkg/controllers/overrider/clusterresource_controller.go [84:158]


func (r *ClusterResourceReconciler) ensureClusterResourceOverrideSnapshot(ctx context.Context, cro *placementv1alpha1.ClusterResourceOverride, revisionHistoryLimit int) error {
	croKObj := klog.KObj(cro)
	overridePolicy := cro.Spec
	overrideSpecHash, err := resource.HashOf(overridePolicy)
	if err != nil {
		klog.ErrorS(err, "Failed to generate policy hash of clusterResourceOverride", "clusterResourceOverride", croKObj)
		return controller.NewUnexpectedBehaviorError(err)
	}
	// we need to list the snapshots anyway since we need to remove the extra snapshots if there are too many of them.
	snapshotList, err := r.listSortedOverrideSnapshots(ctx, cro)
	if err != nil {
		return err
	}
	// delete redundant snapshot revisions before creating a new snapshot to guarantee that the number of snapshots
	// won't exceed the limit.
	if err = r.removeExtraSnapshot(ctx, snapshotList, revisionHistoryLimit); err != nil {
		return err
	}

	latestSnapshotIndex := -1 //so index start at 0
	if len(snapshotList.Items) != 0 {
		// convert the last unstructured snapshot to the typed object
		latestSnapshot := &placementv1alpha1.ClusterResourceOverrideSnapshot{}
		if err = runtime.DefaultUnstructuredConverter.FromUnstructured(snapshotList.Items[len(snapshotList.Items)-1].Object, latestSnapshot); err != nil {
			klog.ErrorS(err, "Invalid overrideSnapshot", "clusterResourceOverride", croKObj, "overrideSnapshot", klog.KObj(&snapshotList.Items[len(snapshotList.Items)-1]))
			return controller.NewUnexpectedBehaviorError(err)
		}
		if string(latestSnapshot.Spec.OverrideHash) == overrideSpecHash {
			// the content has not changed, so we don't need to create a new snapshot.
			return r.ensureSnapshotLatest(ctx, latestSnapshot)
		}
		// mark the last policy snapshot as inactive if it is different from what we have now.
		if latestSnapshot.Labels[placementv1beta1.IsLatestSnapshotLabel] == strconv.FormatBool(true) {
			// set the latest label to false first to make sure there is only one or none active policy snapshot
			latestSnapshot.Labels[placementv1beta1.IsLatestSnapshotLabel] = strconv.FormatBool(false)
			if err := r.Client.Update(ctx, latestSnapshot); err != nil {
				klog.ErrorS(err, "Failed to set the isLatestSnapshot label to false", "clusterResourceOverride", croKObj, "overrideSnapshot", klog.KObj(latestSnapshot))
				return controller.NewUpdateIgnoreConflictError(err)
			}
			klog.V(2).InfoS("Marked the latest overrideSnapshot as inactive", "clusterResourceOverride", croKObj, "overrideSnapshot", klog.KObj(latestSnapshot))
		}
		// we need to figure out the last snapshot index.
		latestSnapshotIndex, err = labels.ExtractIndex(latestSnapshot, placementv1alpha1.OverrideIndexLabel)
		if err != nil {
			klog.ErrorS(err, "Failed to parse the override index label", "clusterResourceOverride", croKObj, "overrideSnapshot", klog.KObj(latestSnapshot))
			return controller.NewUnexpectedBehaviorError(err)
		}
	}

	// Need to create new snapshot when 1) there is no snapshots or 2) the latest snapshot hash != current one.
	latestSnapshotIndex++
	newSnapshot := &placementv1alpha1.ClusterResourceOverrideSnapshot{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf(placementv1alpha1.OverrideSnapshotNameFmt, cro.Name, latestSnapshotIndex),
			Labels: map[string]string{
				placementv1alpha1.OverrideTrackingLabel: cro.Name,
				placementv1beta1.IsLatestSnapshotLabel:  strconv.FormatBool(true),
				placementv1alpha1.OverrideIndexLabel:    strconv.Itoa(latestSnapshotIndex),
			},
			OwnerReferences: []metav1.OwnerReference{
				*metav1.NewControllerRef(cro, placementv1alpha1.GroupVersion.WithKind(placementv1alpha1.ClusterResourceOverrideKind)),
			},
		},
		Spec: placementv1alpha1.ClusterResourceOverrideSnapshotSpec{
			OverrideSpec: overridePolicy,
			OverrideHash: []byte(overrideSpecHash),
		},
	}
	if err := r.Client.Create(ctx, newSnapshot); err != nil {
		klog.ErrorS(err, "Failed to create new overrideSnapshot", "newOverrideSnapshot", klog.KObj(newSnapshot))
		return controller.NewAPIServerError(false, err)
	}
	klog.V(2).InfoS("Created new overrideSnapshot", "clusterResourceOverride", croKObj, "newOverrideSnapshot", klog.KObj(newSnapshot))
	return nil
}