diff --git a/pkg/controller/controllerutil/controllerutil.go b/pkg/controller/controllerutil/controllerutil.go index 1c679668dc..d0a576c034 100644 --- a/pkg/controller/controllerutil/controllerutil.go +++ b/pkg/controller/controllerutil/controllerutil.go @@ -60,6 +60,17 @@ func SetControllerReference(owner, object metav1.Object, scheme *runtime.Scheme) return fmt.Errorf("%T is not a runtime.Object, cannot call SetControllerReference", owner) } + ownerNs := owner.GetNamespace() + if ownerNs != "" { + objNs := object.GetNamespace() + if objNs == "" { + return fmt.Errorf("cluster-scoped resource must not have a namespace-scoped owner, owner's namespace %s", ownerNs) + } + if ownerNs != objNs { + return fmt.Errorf("cross-namespace owner references are disallowed, owner's namespace %s, obj's namespace %s", owner.GetNamespace(), object.GetNamespace()) + } + } + gvk, err := apiutil.GVKForObject(ro, scheme) if err != nil { return err diff --git a/pkg/controller/controllerutil/controllerutil_test.go b/pkg/controller/controllerutil/controllerutil_test.go index 9863a003a3..ff9ea56b73 100644 --- a/pkg/controller/controllerutil/controllerutil_test.go +++ b/pkg/controller/controllerutil/controllerutil_test.go @@ -115,6 +115,24 @@ var _ = Describe("Controllerutil", func() { BlockOwnerDeletion: &t, })) }) + + It("should return an error if it's setting a cross-namespace owner reference", func() { + rs := &appsv1.ReplicaSet{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "namespace1"}} + dep := &extensionsv1beta1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "namespace2", UID: "foo-uid"}} + + err := controllerutil.SetControllerReference(dep, rs, scheme.Scheme) + + Expect(err).To(HaveOccurred()) + }) + + It("should return an error if it's owner is namespaced resource but dependant is cluster-scoped resource", func() { + pv := &corev1.PersistentVolume{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default", UID: "foo-uid"}} + + err := controllerutil.SetControllerReference(pod, pv, scheme.Scheme) + + Expect(err).To(HaveOccurred()) + }) }) Describe("CreateOrUpdate", func() {