in pkg/util/clienthelper/clienthelper.go [149:274]
func Merge(old, new client.Object) (client.Object, bool, string, error) {
if reflect.TypeOf(old) != reflect.TypeOf(new) {
return nil, false, "", fmt.Errorf("types differ: %T %T", old, new)
}
// 1. Set defaults on new. This gets rid of many false positive diffs.
scheme.Scheme.Default(new)
// 2. Copy immutable fields from old to new to avoid false positives.
oldtypemeta := old.GetObjectKind()
newtypemeta := new.GetObjectKind()
newtypemeta.SetGroupVersionKind(oldtypemeta.GroupVersionKind())
new.SetSelfLink(old.GetSelfLink())
new.SetUID(old.GetUID())
new.SetResourceVersion(old.GetResourceVersion())
new.SetGeneration(old.GetGeneration())
new.SetCreationTimestamp(old.GetCreationTimestamp())
new.SetManagedFields(old.GetManagedFields())
// 3. Do fix-ups on a per-Kind basis.
switch old.(type) {
case *corev1.Namespace:
old, new := old.(*corev1.Namespace), new.(*corev1.Namespace)
for _, name := range []string{
"openshift.io/sa.scc.mcs",
"openshift.io/sa.scc.supplemental-groups",
"openshift.io/sa.scc.uid-range",
} {
copyAnnotation(&new.ObjectMeta, &old.ObjectMeta, name)
}
// Copy OLM label
for k := range old.Labels {
if strings.HasPrefix(k, "olm.operatorgroup.uid/") {
copyLabel(&new.ObjectMeta, &old.ObjectMeta, k)
}
}
new.Spec.Finalizers = old.Spec.Finalizers
new.Status = old.Status
case *corev1.ServiceAccount:
old, new := old.(*corev1.ServiceAccount), new.(*corev1.ServiceAccount)
for _, name := range maps.Keys(old.ObjectMeta.Annotations) {
if strings.HasPrefix(name, "openshift.io/") {
copyAnnotation(&new.ObjectMeta, &old.ObjectMeta, name)
}
}
new.Secrets = old.Secrets
new.ImagePullSecrets = old.ImagePullSecrets
case *corev1.Service:
old, new := old.(*corev1.Service), new.(*corev1.Service)
new.Spec.ClusterIP = old.Spec.ClusterIP
case *appsv1.DaemonSet:
old, new := old.(*appsv1.DaemonSet), new.(*appsv1.DaemonSet)
copyAnnotation(&new.ObjectMeta, &old.ObjectMeta, "deprecated.daemonset.template.generation")
new.Status = old.Status
case *appsv1.Deployment:
old, new := old.(*appsv1.Deployment), new.(*appsv1.Deployment)
copyAnnotation(&new.ObjectMeta, &old.ObjectMeta, "deployment.kubernetes.io/revision")
// populated automatically by the Kubernetes API (observed on 4.9)
if old.Spec.Template.Spec.DeprecatedServiceAccount != "" {
new.Spec.Template.Spec.DeprecatedServiceAccount = old.Spec.Template.Spec.DeprecatedServiceAccount
}
new.Status = old.Status
case *mcv1.KubeletConfig:
old, new := old.(*mcv1.KubeletConfig), new.(*mcv1.KubeletConfig)
new.Status = old.Status
case *extensionsv1.CustomResourceDefinition:
old, new := old.(*extensionsv1.CustomResourceDefinition), new.(*extensionsv1.CustomResourceDefinition)
new.Status = old.Status
case *arov1alpha1.Cluster:
old, new := old.(*arov1alpha1.Cluster), new.(*arov1alpha1.Cluster)
new.Status = old.Status
case *hivev1.ClusterDeployment:
old, new := old.(*hivev1.ClusterDeployment), new.(*hivev1.ClusterDeployment)
new.ObjectMeta.Finalizers = old.ObjectMeta.Finalizers
new.Status = old.Status
for _, name := range maps.Keys(old.ObjectMeta.Labels) {
if strings.HasPrefix(name, "hive.openshift.io/") {
copyLabel(&new.ObjectMeta, &old.ObjectMeta, name)
}
}
// Copy over the ClusterMetadata.Platform that Hive generates
if old.Spec.ClusterMetadata.Platform != nil {
new.Spec.ClusterMetadata.Platform = old.Spec.ClusterMetadata.Platform
}
case *corev1.ConfigMap:
old, new := old.(*corev1.ConfigMap), new.(*corev1.ConfigMap)
_, injectTrustBundle := new.ObjectMeta.Labels["config.openshift.io/inject-trusted-cabundle"]
if injectTrustBundle {
caBundle, ext := old.Data["ca-bundle.crt"]
if ext {
new.Data["ca-bundle.crt"] = caBundle
}
// since OCP 4.15 this annotation is added to the trusted-ca-bundle ConfigMap by the ConfigMap's controller
copyAnnotation(&new.ObjectMeta, &old.ObjectMeta, "openshift.io/owning-component")
}
case *machinev1beta1.MachineHealthCheck:
old, new := old.(*machinev1beta1.MachineHealthCheck), new.(*machinev1beta1.MachineHealthCheck)
new.Status = old.Status
}
var diff string
if _, ok := old.(*corev1.Secret); !ok { // Don't show a diff if kind is Secret
diff = strings.Join(deep.Equal(old, new), "\n")
} else {
diff = "<scrubbed>"
}
return new, !reflect.DeepEqual(old, new), diff, nil
}