deletePod handler in the deployment controller shouldn't set owner refs

This commit is contained in:
Bo Ingram 2017-06-04 20:04:13 -06:00
parent 3837d95191
commit 5a99edaeb0
3 changed files with 81 additions and 11 deletions

View File

@ -356,7 +356,7 @@ func (dc *DeploymentController) deletePod(obj interface{}) {
glog.V(4).Infof("Pod %s deleted.", pod.Name) glog.V(4).Infof("Pod %s deleted.", pod.Name)
if d := dc.getDeploymentForPod(pod); d != nil && d.Spec.Strategy.Type == extensions.RecreateDeploymentStrategyType { if d := dc.getDeploymentForPod(pod); d != nil && d.Spec.Strategy.Type == extensions.RecreateDeploymentStrategyType {
// Sync if this Deployment now has no more Pods. // Sync if this Deployment now has no more Pods.
rsList, err := dc.getReplicaSetsForDeployment(d) rsList, err := util.ListReplicaSets(d, util.RsListFromClient(dc.client))
if err != nil { if err != nil {
return return
} }

View File

@ -415,11 +415,81 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) {
foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType
rs := newReplicaSet(foo, "foo-1", 1) rs1 := newReplicaSet(foo, "foo-1", 1)
pod := generatePodFromRS(rs) rs2 := newReplicaSet(foo, "foo-1", 1)
pod1 := generatePodFromRS(rs1)
pod2 := generatePodFromRS(rs2)
f.dLister = append(f.dLister, foo) f.dLister = append(f.dLister, foo)
f.rsLister = append(f.rsLister, rs) // Let's pretend this is a different pod. The gist is that the pod lister needs to
// return a non-empty list.
f.podLister = append(f.podLister, pod1, pod2)
c, _ := f.newController()
enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" {
enqueued = true
}
}
c.deletePod(pod1)
if enqueued {
t.Errorf("expected deployment %q not to be queued after pod deletion", foo.Name)
}
}
// TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment ensures that
// the deletion of a pod will requeue a Recreate deployment iff there is no other
// pod returned from the client in the case where a deployment has multiple replica
// sets, some of which have empty owner references.
func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testing.T) {
f := newFixture(t)
foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType
rs1 := newReplicaSet(foo, "foo-1", 1)
rs2 := newReplicaSet(foo, "foo-2", 2)
rs2.OwnerReferences = nil
pod := generatePodFromRS(rs1)
f.dLister = append(f.dLister, foo)
f.rsLister = append(f.rsLister, rs1, rs2)
f.objects = append(f.objects, foo, rs1, rs2)
c, _ := f.newController()
enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" {
enqueued = true
}
}
c.deletePod(pod)
if !enqueued {
t.Errorf("expected deployment %q to be queued after pod deletion", foo.Name)
}
}
// TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment that the
// deletion of a pod will not requeue a Recreate deployment iff there are other pods
// returned from the client in the case where a deployment has multiple replica sets,
// some of which have empty owner references.
func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t *testing.T) {
f := newFixture(t)
foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"})
foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType
rs1 := newReplicaSet(foo, "foo-1", 1)
rs2 := newReplicaSet(foo, "foo-2", 2)
rs2.OwnerReferences = nil
pod := generatePodFromRS(rs1)
f.dLister = append(f.dLister, foo)
f.rsLister = append(f.rsLister, rs1, rs2)
f.objects = append(f.objects, foo, rs1, rs2)
// Let's pretend this is a different pod. The gist is that the pod lister needs to // Let's pretend this is a different pod. The gist is that the pod lister needs to
// return a non-empty list. // return a non-empty list.
f.podLister = append(f.podLister, pod) f.podLister = append(f.podLister, pod)

View File

@ -489,7 +489,7 @@ func getReplicaSetFraction(rs extensions.ReplicaSet, d extensions.Deployment) in
// Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets. // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets.
// The third returned value is the new replica set, and it may be nil if it doesn't exist yet. // The third returned value is the new replica set, and it may be nil if it doesn't exist yet.
func GetAllReplicaSets(deployment *extensions.Deployment, c clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, *extensions.ReplicaSet, error) { func GetAllReplicaSets(deployment *extensions.Deployment, c clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, *extensions.ReplicaSet, error) {
rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -507,7 +507,7 @@ func GetAllReplicaSets(deployment *extensions.Deployment, c clientset.Interface)
// GetOldReplicaSets returns the old replica sets targeted by the given Deployment; get PodList and ReplicaSetList from client interface. // GetOldReplicaSets returns the old replica sets targeted by the given Deployment; get PodList and ReplicaSetList from client interface.
// Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets. // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets.
func GetOldReplicaSets(deployment *extensions.Deployment, c clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { func GetOldReplicaSets(deployment *extensions.Deployment, c clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) {
rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -517,15 +517,15 @@ func GetOldReplicaSets(deployment *extensions.Deployment, c clientset.Interface)
// GetNewReplicaSet returns a replica set that matches the intent of the given deployment; get ReplicaSetList from client interface. // GetNewReplicaSet returns a replica set that matches the intent of the given deployment; get ReplicaSetList from client interface.
// Returns nil if the new replica set doesn't exist yet. // Returns nil if the new replica set doesn't exist yet.
func GetNewReplicaSet(deployment *extensions.Deployment, c clientset.Interface) (*extensions.ReplicaSet, error) { func GetNewReplicaSet(deployment *extensions.Deployment, c clientset.Interface) (*extensions.ReplicaSet, error) {
rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) rsList, err := ListReplicaSets(deployment, RsListFromClient(c))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return FindNewReplicaSet(deployment, rsList) return FindNewReplicaSet(deployment, rsList)
} }
// rsListFromClient returns an rsListFunc that wraps the given client. // RsListFromClient returns an rsListFunc that wraps the given client.
func rsListFromClient(c clientset.Interface) rsListFunc { func RsListFromClient(c clientset.Interface) RsListFunc {
return func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) { return func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) {
rsList, err := c.Extensions().ReplicaSets(namespace).List(options) rsList, err := c.Extensions().ReplicaSets(namespace).List(options)
if err != nil { if err != nil {
@ -547,14 +547,14 @@ func podListFromClient(c clientset.Interface) podListFunc {
} }
// TODO: switch this to full namespacers // TODO: switch this to full namespacers
type rsListFunc func(string, metav1.ListOptions) ([]*extensions.ReplicaSet, error) type RsListFunc func(string, metav1.ListOptions) ([]*extensions.ReplicaSet, error)
type podListFunc func(string, metav1.ListOptions) (*v1.PodList, error) type podListFunc func(string, metav1.ListOptions) (*v1.PodList, error)
// ListReplicaSets returns a slice of RSes the given deployment targets. // ListReplicaSets returns a slice of RSes the given deployment targets.
// Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan), // Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan),
// because only the controller itself should do that. // because only the controller itself should do that.
// However, it does filter out anything whose ControllerRef doesn't match. // However, it does filter out anything whose ControllerRef doesn't match.
func ListReplicaSets(deployment *extensions.Deployment, getRSList rsListFunc) ([]*extensions.ReplicaSet, error) { func ListReplicaSets(deployment *extensions.Deployment, getRSList RsListFunc) ([]*extensions.ReplicaSet, error) {
// TODO: Right now we list replica sets by their labels. We should list them by selector, i.e. the replica set's selector // TODO: Right now we list replica sets by their labels. We should list them by selector, i.e. the replica set's selector
// should be a superset of the deployment's selector, see https://github.com/kubernetes/kubernetes/issues/19830. // should be a superset of the deployment's selector, see https://github.com/kubernetes/kubernetes/issues/19830.
namespace := deployment.Namespace namespace := deployment.Namespace