func (e vcEquality) CheckUWPodStatusEquality(pObj, vObj *v1.Pod) *v1.PodStatus {
	newVStatus := pObj.Status.DeepCopy()
	vReadinessGateSet := sets.NewString()
	for _, r := range vObj.Spec.ReadinessGates {
		vReadinessGateSet.Insert(string(r.ConditionType))
	}
	pReadinessGateSet := sets.NewString()
	for _, r := range pObj.Spec.ReadinessGates {
		pReadinessGateSet.Insert(string(r.ConditionType))
	}
	vConditionMap := make(map[string]v1.PodCondition)
	for _, c := range vObj.Status.Conditions {
		if vReadinessGateSet.Has(string(c.Type)) {
			vConditionMap[string(c.Type)] = c
		}
	}
	for i := 0; i < len(newVStatus.Conditions); i++ {
		c := newVStatus.Conditions[i]
		if !pReadinessGateSet.Has(string(c.Type)) && !vReadinessGateSet.Has(string(c.Type)) {
			continue
		}
		if !vReadinessGateSet.Has(string(c.Type)) {
			newVStatus.Conditions = append(newVStatus.Conditions[:i], newVStatus.Conditions[i+1:]...)
			i--
			continue
		}
		pc, exists := vConditionMap[string(c.Type)]
		if exists {
			delete(vConditionMap, string(c.Type))
			newVStatus.Conditions[i] = *pc.DeepCopy()
		}
	}
	for _, c := range vConditionMap {
		newVStatus.Conditions = append(newVStatus.Conditions, c)
	}
	if !equality.Semantic.DeepEqual(vObj.Status, *newVStatus) {
		return newVStatus
	}
	return nil
}
CheckUWPodStatusEquality compute status upward to tenant.
User-defined readiness type condition unchanged in tenant, others
keep consistent with super.
package conversion
import (
	"strings"
	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	v1 "k8s.io/api/core/v1"
	v1beta1extensions "k8s.io/api/extensions/v1beta1"
	v1scheduling "k8s.io/api/scheduling/v1"
	v1storage "k8s.io/api/storage/v1"
	"k8s.io/apimachinery/pkg/api/equality"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/utils/pointer"
	"sigs.k8s.io/cluster-api-provider-nested/virtualcluster/pkg/apis/tenancy/v1alpha1"
	"sigs.k8s.io/cluster-api-provider-nested/virtualcluster/pkg/syncer/apis/config"
	"sigs.k8s.io/cluster-api-provider-nested/virtualcluster/pkg/syncer/constants"
)
type vcEquality struct {
	config *config.SyncerConfiguration
	vc     *v1alpha1.VirtualCluster
}
func Equality(syncerConfig *config.SyncerConfiguration, vc *v1alpha1.VirtualCluster) *vcEquality {
	return &vcEquality{config: syncerConfig, vc: vc}
}
func (e vcEquality) CheckPodEquality(pPod, vPod *v1.Pod) *v1.Pod {
	var updatedPod *v1.Pod
	updatedMeta := e.CheckDWObjectMetaEquality(&pPod.ObjectMeta, &vPod.ObjectMeta)
	if updatedMeta != nil {
		if updatedPod == nil {
			updatedPod = pPod.DeepCopy()
		}
		updatedPod.ObjectMeta = *updatedMeta
	}
	updatedPodSpec := e.checkPodSpecEquality(&pPod.Spec, &vPod.Spec)
	if updatedPodSpec != nil {
		if updatedPod == nil {
			updatedPod = pPod.DeepCopy()
		}
		updatedPod.Spec = *updatedPodSpec
	}
	return updatedPod
}
func CheckDWPodConditionEquality(pPod, vPod *v1.Pod) *v1.PodStatus {
	readinessGateSet := sets.NewString()
	for _, r := range vPod.Spec.ReadinessGates {
		readinessGateSet.Insert(string(r.ConditionType))
	}
	vConditionMap := make(map[string]v1.PodCondition)
	for _, c := range vPod.Status.Conditions {
		if readinessGateSet.Has(string(c.Type)) {
			vConditionMap[string(c.Type)] = c
		}
	}
	newPStatus := pPod.Status.DeepCopy()
	for i, c := range newPStatus.Conditions {
		if !readinessGateSet.Has(string(c.Type)) {
			continue
		}
		vc, exists := vConditionMap[string(c.Type)]
		if exists {
			delete(vConditionMap, string(c.Type))
			newPStatus.Conditions[i] = *vc.DeepCopy()
		}
	}
	for _, c := range vConditionMap {
		newPStatus.Conditions = append(newPStatus.Conditions, c)
	}
	if !equality.Semantic.DeepEqual(pPod.Status, *newPStatus) {
		return newPStatus
	}
	return nil
}
func (e vcEquality) CheckDWObjectMetaEquality(pObj, vObj *metav1.ObjectMeta) *metav1.ObjectMeta {
	var updatedObj *metav1.ObjectMeta
	if pObj.GenerateName != vObj.GenerateName {
		if updatedObj == nil {
			updatedObj = pObj.DeepCopy()
		}
		updatedObj.GenerateName = vObj.GenerateName
	}
	labels, equal := e.checkDWKVEquality(pObj.Labels, vObj.Labels)
	if !equal {
		if updatedObj == nil {
			updatedObj = pObj.DeepCopy()
		}
		updatedObj.Labels = labels
	}
	annotations, equal := e.checkDWKVEquality(pObj.Annotations, vObj.Annotations)
	if !equal {
		if updatedObj == nil {
			updatedObj = pObj.DeepCopy()
		}
		updatedObj.Annotations = annotations
	}
	if pObj.ClusterName != vObj.ClusterName {
		if updatedObj == nil {
			updatedObj = pObj.DeepCopy()
		}
		updatedObj.ClusterName = vObj.ClusterName
	}
	return updatedObj
}
func hasPrefixInArray(key string, array []string) bool {
	for _, item := range array {
		if strings.HasPrefix(key, item) {
			return true
		}
	}
	return false
}
func (e vcEquality) CheckUWObjectMetaEquality(pObj, vObj *metav1.ObjectMeta) *metav1.ObjectMeta {
	var updatedObj *metav1.ObjectMeta
	labels, equal := e.checkUWKVEquality(pObj.Labels, vObj.Labels)
	if !equal {
		if updatedObj == nil {
			updatedObj = vObj.DeepCopy()
		}
		updatedObj.Labels = labels
	}
	annotations, equal := e.checkUWKVEquality(pObj.Annotations, vObj.Annotations)
	if !equal {
		if updatedObj == nil {
			updatedObj = vObj.DeepCopy()
		}
		updatedObj.Annotations = annotations
	}
	return updatedObj
}
func (e vcEquality) checkUWKVEquality(pKV, vKV map[string]string) (map[string]string, bool) {
	if e.vc == nil {
		return nil, true
	}
	matchingSet := sets.NewString(constants.DefaultTransparentMetaPrefix)
	matchingSet.Insert(e.vc.Spec.TransparentMetaPrefixes...)
	matchingList := matchingSet.UnsortedList()
	moreOrDiff := make(map[string]string)
	for pk, pv := range pKV {
		if hasPrefixInArray(pk, matchingList) {
			vv, ok := vKV[pk]
			if !ok || pv != vv {
				moreOrDiff[pk] = pv
			}
		}
	}
	if len(moreOrDiff) == 0 {
		return nil, true
	}
	updated := make(map[string]string)
	for k, v := range vKV {
		updated[k] = v
	}
	for k, v := range moreOrDiff {
		updated[k] = v
	}
	return updated, false
}
func (e vcEquality) checkDWKVEquality(pKV, vKV map[string]string) (map[string]string, bool) {
	var exceptionsList []string
	if e.vc != nil {
		exceptions := sets.NewString()
		exceptions.Insert(e.vc.Spec.TransparentMetaPrefixes...)
		exceptions.Insert(e.vc.Spec.OpaqueMetaPrefixes...)
		exceptions.Insert(constants.DefaultOpaqueMetaPrefix, constants.DefaultTransparentMetaPrefix)
		exceptionsList = exceptions.UnsortedList()
	}
	moreOrDiff := make(map[string]string)
	for vk, vv := range vKV {
		if hasPrefixInArray(vk, exceptionsList) {
			continue
		}
		if isOpaquedKey(e.config, vk) {
			continue
		}
		pv, ok := pKV[vk]
		if !ok || pv != vv {
			moreOrDiff[vk] = vv
		}
	}
	less := make(map[string]string)
	for pk := range pKV {
		if hasPrefixInArray(pk, exceptionsList) {
			continue
		}
		if isOpaquedKey(e.config, pk) {
			continue
		}
		vv, ok := vKV[pk]
		if !ok {
			less[pk] = vv
		}
	}
	if len(moreOrDiff) == 0 && len(less) == 0 {
		return nil, true
	}
	updated := make(map[string]string)
	for k, v := range pKV {
		if _, ok := less[k]; ok {
			continue
		}
		updated[k] = v
	}
	for k, v := range moreOrDiff {
		updated[k] = v
	}
	return updated, false
}
func isOpaquedKey(config *config.SyncerConfiguration, key string) bool {
	if config == nil {
		return false
	}
	tokens := strings.SplitN(key, "/", 2)
	if len(tokens) < 1 {
		return false
	}
	for _, domain := range config.DefaultOpaqueMetaDomains {
		if strings.HasSuffix(tokens[0], domain) {
			return true
		}
	}
	return false
}