Skip to content

Commit

Permalink
UPSTREAM: 56864: pick pod-selector changes from kubernetes#56864
Browse files Browse the repository at this point in the history
:100644 100644 910654f6f6... 37f3ef1175... M	pkg/kubectl/cmd/drain.go
  • Loading branch information
juanvallejo authored and deads2k committed Jan 2, 2018
1 parent b68cbb8 commit 6cd0c69
Showing 1 changed file with 30 additions and 51 deletions.
81 changes: 30 additions & 51 deletions pkg/kubectl/cmd/drain.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/json"
Expand Down Expand Up @@ -61,6 +62,7 @@ type DrainOptions struct {
backOff clockwork.Clock
DeleteLocalData bool
Selector string
PodSelector string
mapper meta.RESTMapper
nodeInfos []*resource.Info
Out io.Writer
Expand Down Expand Up @@ -197,6 +199,8 @@ func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
cmd.Flags().IntVar(&options.GracePeriodSeconds, "grace-period", -1, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.")
cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up, zero means infinite")
cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on")
cmd.Flags().StringVarP(&options.PodSelector, "pod-selector", "", options.PodSelector, "Label selector to filter pods on the node")

cmdutil.AddDryRunFlag(cmd)
return cmd
}
Expand All @@ -223,6 +227,12 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error {
return err
}

if len(o.PodSelector) > 0 {
if _, err := labels.Parse(o.PodSelector); err != nil {
return errors.New("--pod-selector=<pod_selector> must be a valid label selector")
}
}

o.restClient, err = o.Factory.RESTClient()
if err != nil {
return err
Expand Down Expand Up @@ -328,38 +338,8 @@ func (o *DrainOptions) deleteOrEvictPodsSimple(nodeInfo *resource.Info) error {
return err
}

func (o *DrainOptions) getController(namespace string, controllerRef *metav1.OwnerReference) (interface{}, error) {
switch controllerRef.Kind {
case "ReplicationController":
return o.client.Core().ReplicationControllers(namespace).Get(controllerRef.Name, metav1.GetOptions{})
case "DaemonSet":
return o.client.Extensions().DaemonSets(namespace).Get(controllerRef.Name, metav1.GetOptions{})
case "Job":
return o.client.Batch().Jobs(namespace).Get(controllerRef.Name, metav1.GetOptions{})
case "ReplicaSet":
return o.client.Extensions().ReplicaSets(namespace).Get(controllerRef.Name, metav1.GetOptions{})
case "StatefulSet":
return o.client.AppsV1beta1().StatefulSets(namespace).Get(controllerRef.Name, metav1.GetOptions{})
}
return nil, fmt.Errorf("Unknown controller kind %q", controllerRef.Kind)
}

func (o *DrainOptions) getPodController(pod corev1.Pod) (*metav1.OwnerReference, error) {
controllerRef := metav1.GetControllerOf(&pod)
if controllerRef == nil {
return nil, nil
}

// We assume the only reason for an error is because the controller is
// gone/missing, not for any other cause.
// TODO(mml): something more sophisticated than this
// TODO(juntee): determine if it's safe to remove getController(),
// so that drain can work for controller types that we don't know about
_, err := o.getController(pod.Namespace, controllerRef)
if err != nil {
return nil, err
}
return controllerRef, nil
func (o *DrainOptions) getPodController(pod corev1.Pod) *metav1.OwnerReference {
return metav1.GetControllerOf(&pod)
}

func (o *DrainOptions) unreplicatedFilter(pod corev1.Pod) (bool, *warning, *fatal) {
Expand All @@ -368,21 +348,15 @@ func (o *DrainOptions) unreplicatedFilter(pod corev1.Pod) (bool, *warning, *fata
return true, nil, nil
}

controllerRef, err := o.getPodController(pod)
if err != nil {
// if we're forcing, remove orphaned pods with a warning
if apierrors.IsNotFound(err) && o.Force {
return true, &warning{err.Error()}, nil
}
return false, nil, &fatal{err.Error()}
}
controllerRef := o.getPodController(pod)
if controllerRef != nil {
return true, nil, nil
}
if !o.Force {
return false, nil, &fatal{kUnmanagedFatal}
if o.Force {
return true, &warning{kUnmanagedWarning}, nil
}
return true, &warning{kUnmanagedWarning}, nil

return false, nil, &fatal{kUnmanagedFatal}
}

func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal) {
Expand All @@ -393,23 +367,22 @@ func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal)
// The exception is for pods that are orphaned (the referencing
// management resource - including DaemonSet - is not found).
// Such pods will be deleted if --force is used.
controllerRef, err := o.getPodController(pod)
if err != nil {
// if we're forcing, remove orphaned pods with a warning
if apierrors.IsNotFound(err) && o.Force {
return true, &warning{err.Error()}, nil
}
return false, nil, &fatal{err.Error()}
}
controllerRef := o.getPodController(pod)
if controllerRef == nil || controllerRef.Kind != "DaemonSet" {
return true, nil, nil
}

if _, err := o.client.Extensions().DaemonSets(pod.Namespace).Get(controllerRef.Name, metav1.GetOptions{}); err != nil {
// remove orphaned pods with a warning if --force is used
if apierrors.IsNotFound(err) && o.Force {
return true, &warning{err.Error()}, nil
}
return false, nil, &fatal{err.Error()}
}
if !o.IgnoreDaemonsets {
return false, nil, &fatal{kDaemonsetFatal}
}

return false, &warning{kDaemonsetWarning}, nil
}

Expand Down Expand Up @@ -455,7 +428,13 @@ func (ps podStatuses) Message() string {
// getPodsForDeletion receives resource info for a node, and returns all the pods from the given node that we
// are planning on deleting. If there are any pods preventing us from deleting, we return that list in an error.
func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []corev1.Pod, err error) {
labelSelector, err := labels.Parse(o.PodSelector)
if err != nil {
return pods, err
}

podList, err := o.client.Core().Pods(metav1.NamespaceAll).List(metav1.ListOptions{
LabelSelector: labelSelector.String(),
FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": nodeInfo.Name}).String()})
if err != nil {
return pods, err
Expand Down

0 comments on commit 6cd0c69

Please sign in to comment.