Deployment: Filter by ControllerRef in Reaper.

We don't want to delete ReplicaSets we don't own.
This commit is contained in:
Anthony Yeh 2017-03-06 14:51:18 -08:00
parent cec3899b96
commit 8c4bcb38fb
4 changed files with 57 additions and 10 deletions

View File

@ -593,6 +593,35 @@ func ListReplicaSets(deployment *extensions.Deployment, getRSList rsListFunc) ([
return owned, nil
}
// ListReplicaSets returns a slice of RSes the given deployment targets.
// Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan),
// because only the controller itself should do that.
// However, it does filter out anything whose ControllerRef doesn't match.
// TODO: Remove the duplicate.
func ListReplicaSetsInternal(deployment *internalextensions.Deployment, getRSList func(string, metav1.ListOptions) ([]*internalextensions.ReplicaSet, error)) ([]*internalextensions.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
// should be a superset of the deployment's selector, see https://github.com/kubernetes/kubernetes/issues/19830.
namespace := deployment.Namespace
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
if err != nil {
return nil, err
}
options := metav1.ListOptions{LabelSelector: selector.String()}
all, err := getRSList(namespace, options)
if err != nil {
return all, err
}
// Only include those whose ControllerRef matches the Deployment.
owned := make([]*internalextensions.ReplicaSet, 0, len(all))
for _, rs := range all {
controllerRef := controller.GetControllerOf(rs)
if controllerRef != nil && controllerRef.UID == deployment.UID {
owned = append(owned, rs)
}
}
return owned, nil
}
// ListPods returns a list of pods the given deployment targets.
// This needs a list of ReplicaSets for the Deployment,
// which can be found with ListReplicaSets().

View File

@ -152,6 +152,7 @@ go_test(
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/intstr",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/util/uuid",
"//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/client-go/rest",
"//vendor:k8s.io/client-go/rest/fake",

View File

@ -420,7 +420,6 @@ func (reaper *JobReaper) Stop(namespace, name string, timeout time.Duration, gra
func (reaper *DeploymentReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error {
deployments := reaper.dClient.Deployments(namespace)
replicaSets := reaper.rsClient.ReplicaSets(namespace)
rsReaper := &ReplicaSetReaper{reaper.rsClient, reaper.pollInterval, reaper.timeout}
deployment, err := reaper.updateDeploymentWithRetries(namespace, name, func(d *extensions.Deployment) {
@ -441,20 +440,26 @@ func (reaper *DeploymentReaper) Stop(namespace, name string, timeout time.Durati
return err
}
// Stop all replica sets.
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
// Stop all replica sets belonging to this Deployment.
rss, err := deploymentutil.ListReplicaSetsInternal(deployment,
func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) {
rsList, err := reaper.rsClient.ReplicaSets(namespace).List(options)
if err != nil {
return nil, err
}
rss := make([]*extensions.ReplicaSet, 0, len(rsList.Items))
for i := range rsList.Items {
rss = append(rss, &rsList.Items[i])
}
return rss, nil
})
if err != nil {
return err
}
options := metav1.ListOptions{LabelSelector: selector.String()}
rsList, err := replicaSets.List(options)
if err != nil {
return err
}
errList := []error{}
for _, rc := range rsList.Items {
if err := rsReaper.Stop(rc.Namespace, rc.Name, timeout, gracePeriod); err != nil {
for _, rs := range rss {
if err := rsReaper.Stop(rs.Namespace, rs.Name, timeout, gracePeriod); err != nil {
scaleGetErr, ok := err.(ScaleError)
if errors.IsNotFound(err) || (ok && errors.IsNotFound(scaleGetErr.ActualError)) {
continue

View File

@ -27,6 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/watch"
testcore "k8s.io/client-go/testing"
"k8s.io/kubernetes/pkg/api"
@ -429,6 +430,7 @@ func TestDeploymentStop(t *testing.T) {
deployment := extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
UID: uuid.NewUUID(),
Namespace: ns,
},
Spec: extensions.DeploymentSpec{
@ -440,6 +442,7 @@ func TestDeploymentStop(t *testing.T) {
},
}
template := deploymentutil.GetNewReplicaSetTemplateInternal(&deployment)
trueVar := true
tests := []struct {
Name string
Objs []runtime.Object
@ -478,6 +481,15 @@ func TestDeploymentStop(t *testing.T) {
Name: name,
Namespace: ns,
Labels: map[string]string{"k1": "v1"},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: extensions.SchemeGroupVersion.String(),
Kind: "ReplicaSet",
Name: deployment.Name,
UID: deployment.UID,
Controller: &trueVar,
},
},
},
Spec: extensions.ReplicaSetSpec{
Template: template,