diff --git a/federation/pkg/federation-controller/configmap/configmap_controller.go b/federation/pkg/federation-controller/configmap/configmap_controller.go index 305333251c..e0a9a26e6d 100644 --- a/federation/pkg/federation-controller/configmap/configmap_controller.go +++ b/federation/pkg/federation-controller/configmap/configmap_controller.go @@ -269,8 +269,9 @@ func (configmapcontroller *ConfigMapController) reconcileConfigMap(configmap typ return } + // Do not modify data. desiredConfigMap := &api_v1.ConfigMap{ - ObjectMeta: util.CopyObjectMeta(baseConfigMap.ObjectMeta), + ObjectMeta: util.DeepCopyRelevantObjectMeta(baseConfigMap.ObjectMeta), Data: baseConfigMap.Data, } diff --git a/federation/pkg/federation-controller/daemonset/daemonset_controller.go b/federation/pkg/federation-controller/daemonset/daemonset_controller.go index 341bd5343a..73cf015e11 100644 --- a/federation/pkg/federation-controller/daemonset/daemonset_controller.go +++ b/federation/pkg/federation-controller/daemonset/daemonset_controller.go @@ -401,9 +401,10 @@ func (daemonsetcontroller *DaemonSetController) reconcileDaemonSet(namespace str return } + // Do not modify. Otherwise make a deep copy. desiredDaemonSet := &extensionsv1.DaemonSet{ - ObjectMeta: util.CopyObjectMeta(baseDaemonSet.ObjectMeta), - Spec: baseDaemonSet.Spec, + ObjectMeta: util.DeepCopyRelevantObjectMeta(baseDaemonSet.ObjectMeta), + Spec: util.DeepCopyApiTypeOrPanic(baseDaemonSet.Spec).(extensionsv1.DaemonSetSpec), } if !found { diff --git a/federation/pkg/federation-controller/deployment/deploymentcontroller.go b/federation/pkg/federation-controller/deployment/deploymentcontroller.go index 148114ddd3..0f791ad64d 100644 --- a/federation/pkg/federation-controller/deployment/deploymentcontroller.go +++ b/federation/pkg/federation-controller/deployment/deploymentcontroller.go @@ -561,9 +561,10 @@ func (fdc *DeploymentController) reconcileDeployment(key string) (reconciliation return statusError, err } + // The object can be modified. ld := &extensionsv1.Deployment{ - ObjectMeta: fedutil.CopyObjectMeta(fd.ObjectMeta), - Spec: fd.Spec, + ObjectMeta: fedutil.DeepCopyRelevantObjectMeta(fd.ObjectMeta), + Spec: fedutil.DeepCopyApiTypeOrPanic(fd.Spec).(extensionsv1.DeploymentSpec), } specReplicas := int32(replicas) ld.Spec.Replicas = &specReplicas diff --git a/federation/pkg/federation-controller/ingress/ingress_controller.go b/federation/pkg/federation-controller/ingress/ingress_controller.go index 4a756ec990..46db3b1b42 100644 --- a/federation/pkg/federation-controller/ingress/ingress_controller.go +++ b/federation/pkg/federation-controller/ingress/ingress_controller.go @@ -735,7 +735,7 @@ func (ic *IngressController) reconcileIngress(ingress types.NamespacedName) { if !clusterIngressFound { glog.V(4).Infof("No existing Ingress %s in cluster %s - checking if appropriate to queue a create operation", ingress, cluster.Name) // We can't supply server-created fields when creating a new object. - desiredIngress.ObjectMeta = util.DeepCopyObjectMeta(baseIngress.ObjectMeta) + desiredIngress.ObjectMeta = util.DeepCopyRelevantObjectMeta(baseIngress.ObjectMeta) ic.eventRecorder.Eventf(baseIngress, api.EventTypeNormal, "CreateInCluster", "Creating ingress in cluster %s", cluster.Name) diff --git a/federation/pkg/federation-controller/namespace/namespace_controller.go b/federation/pkg/federation-controller/namespace/namespace_controller.go index 5347d3ce66..07a1c3731f 100644 --- a/federation/pkg/federation-controller/namespace/namespace_controller.go +++ b/federation/pkg/federation-controller/namespace/namespace_controller.go @@ -391,9 +391,10 @@ func (nc *NamespaceController) reconcileNamespace(namespace string) { nc.deliverNamespace(namespace, 0, true) return } + // The object should not be modified. desiredNamespace := &api_v1.Namespace{ - ObjectMeta: util.CopyObjectMeta(baseNamespace.ObjectMeta), - Spec: baseNamespace.Spec, + ObjectMeta: util.DeepCopyRelevantObjectMeta(baseNamespace.ObjectMeta), + Spec: util.DeepCopyApiTypeOrPanic(baseNamespace.Spec).(api_v1.NamespaceSpec), } glog.V(5).Infof("Desired namespace in underlying clusters: %+v", desiredNamespace) diff --git a/federation/pkg/federation-controller/replicaset/replicasetcontroller.go b/federation/pkg/federation-controller/replicaset/replicasetcontroller.go index 75984fd1f4..1d7495e1de 100644 --- a/federation/pkg/federation-controller/replicaset/replicasetcontroller.go +++ b/federation/pkg/federation-controller/replicaset/replicasetcontroller.go @@ -562,9 +562,10 @@ func (frsc *ReplicaSetController) reconcileReplicaSet(key string) (reconciliatio return statusError, err } + // The object can be modified. lrs := &extensionsv1.ReplicaSet{ - ObjectMeta: fedutil.CopyObjectMeta(frs.ObjectMeta), - Spec: frs.Spec, + ObjectMeta: fedutil.DeepCopyRelevantObjectMeta(frs.ObjectMeta), + Spec: fedutil.DeepCopyApiTypeOrPanic(frs.Spec).(extensionsv1.ReplicaSetSpec), } specReplicas := int32(replicas) lrs.Spec.Replicas = &specReplicas diff --git a/federation/pkg/federation-controller/secret/secret_controller.go b/federation/pkg/federation-controller/secret/secret_controller.go index 120f3dffc1..593cb9cc37 100644 --- a/federation/pkg/federation-controller/secret/secret_controller.go +++ b/federation/pkg/federation-controller/secret/secret_controller.go @@ -366,8 +366,9 @@ func (secretcontroller *SecretController) reconcileSecret(secret types.Namespace return } + // The data should not be modified. desiredSecret := &api_v1.Secret{ - ObjectMeta: util.CopyObjectMeta(baseSecret.ObjectMeta), + ObjectMeta: util.DeepCopyRelevantObjectMeta(baseSecret.ObjectMeta), Data: baseSecret.Data, Type: baseSecret.Type, } diff --git a/federation/pkg/federation-controller/util/BUILD b/federation/pkg/federation-controller/util/BUILD index 5e81263206..442f3bd5c2 100644 --- a/federation/pkg/federation-controller/util/BUILD +++ b/federation/pkg/federation-controller/util/BUILD @@ -36,6 +36,7 @@ go_library( "//pkg/client/restclient:go_default_library", "//pkg/client/unversioned/clientcmd:go_default_library", "//pkg/client/unversioned/clientcmd/api:go_default_library", + "//pkg/conversion:go_default_library", "//pkg/runtime:go_default_library", "//pkg/util/flowcontrol:go_default_library", "//pkg/util/net:go_default_library", diff --git a/federation/pkg/federation-controller/util/meta.go b/federation/pkg/federation-controller/util/meta.go index ed40df5b3d..75c7fa141f 100644 --- a/federation/pkg/federation-controller/util/meta.go +++ b/federation/pkg/federation-controller/util/meta.go @@ -20,13 +20,14 @@ import ( "reflect" api_v1 "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/runtime" ) // Copies cluster-independent, user provided data from the given ObjectMeta struct. If in // the future the ObjectMeta structure is expanded then any field that is not populated // by the api server should be included here. -func CopyObjectMeta(obj api_v1.ObjectMeta) api_v1.ObjectMeta { +func copyObjectMeta(obj api_v1.ObjectMeta) api_v1.ObjectMeta { return api_v1.ObjectMeta{ Name: obj.Name, Namespace: obj.Namespace, @@ -38,8 +39,8 @@ func CopyObjectMeta(obj api_v1.ObjectMeta) api_v1.ObjectMeta { // Deep copies cluster-independent, user provided data from the given ObjectMeta struct. If in // the future the ObjectMeta structure is expanded then any field that is not populated // by the api server should be included here. -func DeepCopyObjectMeta(obj api_v1.ObjectMeta) api_v1.ObjectMeta { - copyMeta := CopyObjectMeta(obj) +func DeepCopyRelevantObjectMeta(obj api_v1.ObjectMeta) api_v1.ObjectMeta { + copyMeta := copyObjectMeta(obj) if obj.Labels != nil { copyMeta.Labels = make(map[string]string) for key, val := range obj.Labels { @@ -83,3 +84,11 @@ func ObjectMetaAndSpecEquivalent(a, b runtime.Object) bool { specB := reflect.ValueOf(b).Elem().FieldByName("Spec").Interface() return ObjectMetaEquivalent(objectMetaA, objectMetaB) && reflect.DeepEqual(specA, specB) } + +func DeepCopyApiTypeOrPanic(item interface{}) interface{} { + result, err := conversion.NewCloner().DeepCopy(item) + if err != nil { + panic(err) + } + return result +} diff --git a/federation/pkg/federation-controller/util/meta_test.go b/federation/pkg/federation-controller/util/meta_test.go index f0c2c88c4f..2a23cacb70 100644 --- a/federation/pkg/federation-controller/util/meta_test.go +++ b/federation/pkg/federation-controller/util/meta_test.go @@ -31,7 +31,7 @@ func TestObjectMeta(t *testing.T) { UID: "1231231412", ResourceVersion: "999", } - o2 := CopyObjectMeta(o1) + o2 := copyObjectMeta(o1) o3 := api_v1.ObjectMeta{ Namespace: "ns1", Name: "s1",