Commit c1802dc4 authored by Ferran Rodenas's avatar Ferran Rodenas

Update kubectl drain command to use policy V1Beta1 instead of unversioned API

parent 94acd5a0
...@@ -72,7 +72,6 @@ go_library( ...@@ -72,7 +72,6 @@ go_library(
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/api/validation:go_default_library", "//pkg/api/validation:go_default_library",
"//pkg/apis/certificates:go_default_library", "//pkg/apis/certificates:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
...@@ -116,6 +115,7 @@ go_library( ...@@ -116,6 +115,7 @@ go_library(
"//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...@@ -139,6 +139,7 @@ go_library( ...@@ -139,6 +139,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/k8s.io/client-go/tools/portforward:go_default_library", "//vendor/k8s.io/client-go/tools/portforward:go_default_library",
...@@ -206,7 +207,6 @@ go_test( ...@@ -206,7 +207,6 @@ go_test(
"//pkg/api/testing:go_default_library", "//pkg/api/testing:go_default_library",
"//pkg/apis/batch:go_default_library", "//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library",
...@@ -223,6 +223,7 @@ go_test( ...@@ -223,6 +223,7 @@ go_test(
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/gopkg.in/yaml.v2:go_default_library", "//vendor/gopkg.in/yaml.v2:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
policyv1beta1 "k8s.io/api/policy/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
...@@ -38,11 +39,9 @@ import ( ...@@ -38,11 +39,9 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
...@@ -51,7 +50,7 @@ import ( ...@@ -51,7 +50,7 @@ import (
) )
type DrainOptions struct { type DrainOptions struct {
client internalclientset.Interface client kubernetes.Interface
restClient *restclient.RESTClient restClient *restclient.RESTClient
Factory cmdutil.Factory Factory cmdutil.Factory
Force bool Force bool
...@@ -71,7 +70,7 @@ type DrainOptions struct { ...@@ -71,7 +70,7 @@ type DrainOptions struct {
// Takes a pod and returns a bool indicating whether or not to operate on the // Takes a pod and returns a bool indicating whether or not to operate on the
// pod, an optional warning message, and an optional fatal error. // pod, an optional warning message, and an optional fatal error.
type podFilter func(api.Pod) (include bool, w *warning, f *fatal) type podFilter func(corev1.Pod) (include bool, w *warning, f *fatal)
type warning struct { type warning struct {
string string
} }
...@@ -220,7 +219,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { ...@@ -220,7 +219,7 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error {
o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run") o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
if o.client, err = o.Factory.ClientSet(); err != nil { if o.client, err = o.Factory.KubernetesClientSet(); err != nil {
return err return err
} }
...@@ -339,12 +338,12 @@ func (o *DrainOptions) getController(namespace string, controllerRef *metav1.Own ...@@ -339,12 +338,12 @@ func (o *DrainOptions) getController(namespace string, controllerRef *metav1.Own
case "ReplicaSet": case "ReplicaSet":
return o.client.Extensions().ReplicaSets(namespace).Get(controllerRef.Name, metav1.GetOptions{}) return o.client.Extensions().ReplicaSets(namespace).Get(controllerRef.Name, metav1.GetOptions{})
case "StatefulSet": case "StatefulSet":
return o.client.Apps().StatefulSets(namespace).Get(controllerRef.Name, metav1.GetOptions{}) return o.client.AppsV1beta1().StatefulSets(namespace).Get(controllerRef.Name, metav1.GetOptions{})
} }
return nil, fmt.Errorf("Unknown controller kind %q", controllerRef.Kind) return nil, fmt.Errorf("Unknown controller kind %q", controllerRef.Kind)
} }
func (o *DrainOptions) getPodController(pod api.Pod) (*metav1.OwnerReference, error) { func (o *DrainOptions) getPodController(pod corev1.Pod) (*metav1.OwnerReference, error) {
controllerRef := metav1.GetControllerOf(&pod) controllerRef := metav1.GetControllerOf(&pod)
if controllerRef == nil { if controllerRef == nil {
return nil, nil return nil, nil
...@@ -362,9 +361,9 @@ func (o *DrainOptions) getPodController(pod api.Pod) (*metav1.OwnerReference, er ...@@ -362,9 +361,9 @@ func (o *DrainOptions) getPodController(pod api.Pod) (*metav1.OwnerReference, er
return controllerRef, nil return controllerRef, nil
} }
func (o *DrainOptions) unreplicatedFilter(pod api.Pod) (bool, *warning, *fatal) { func (o *DrainOptions) unreplicatedFilter(pod corev1.Pod) (bool, *warning, *fatal) {
// any finished pod can be removed // any finished pod can be removed
if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
return true, nil, nil return true, nil, nil
} }
...@@ -385,7 +384,7 @@ func (o *DrainOptions) unreplicatedFilter(pod api.Pod) (bool, *warning, *fatal) ...@@ -385,7 +384,7 @@ func (o *DrainOptions) unreplicatedFilter(pod api.Pod) (bool, *warning, *fatal)
return true, &warning{kUnmanagedWarning}, nil return true, &warning{kUnmanagedWarning}, nil
} }
func (o *DrainOptions) daemonsetFilter(pod api.Pod) (bool, *warning, *fatal) { func (o *DrainOptions) daemonsetFilter(pod corev1.Pod) (bool, *warning, *fatal) {
// Note that we return false in cases where the pod is DaemonSet managed, // Note that we return false in cases where the pod is DaemonSet managed,
// regardless of flags. We never delete them, the only question is whether // regardless of flags. We never delete them, the only question is whether
// their presence constitutes an error. // their presence constitutes an error.
...@@ -413,14 +412,14 @@ func (o *DrainOptions) daemonsetFilter(pod api.Pod) (bool, *warning, *fatal) { ...@@ -413,14 +412,14 @@ func (o *DrainOptions) daemonsetFilter(pod api.Pod) (bool, *warning, *fatal) {
return false, &warning{kDaemonsetWarning}, nil return false, &warning{kDaemonsetWarning}, nil
} }
func mirrorPodFilter(pod api.Pod) (bool, *warning, *fatal) { func mirrorPodFilter(pod corev1.Pod) (bool, *warning, *fatal) {
if _, found := pod.ObjectMeta.Annotations[corev1.MirrorPodAnnotationKey]; found { if _, found := pod.ObjectMeta.Annotations[corev1.MirrorPodAnnotationKey]; found {
return false, nil, nil return false, nil, nil
} }
return true, nil, nil return true, nil, nil
} }
func hasLocalStorage(pod api.Pod) bool { func hasLocalStorage(pod corev1.Pod) bool {
for _, volume := range pod.Spec.Volumes { for _, volume := range pod.Spec.Volumes {
if volume.EmptyDir != nil { if volume.EmptyDir != nil {
return true return true
...@@ -430,7 +429,7 @@ func hasLocalStorage(pod api.Pod) bool { ...@@ -430,7 +429,7 @@ func hasLocalStorage(pod api.Pod) bool {
return false return false
} }
func (o *DrainOptions) localStorageFilter(pod api.Pod) (bool, *warning, *fatal) { func (o *DrainOptions) localStorageFilter(pod corev1.Pod) (bool, *warning, *fatal) {
if !hasLocalStorage(pod) { if !hasLocalStorage(pod) {
return true, nil, nil return true, nil, nil
} }
...@@ -454,7 +453,7 @@ func (ps podStatuses) Message() string { ...@@ -454,7 +453,7 @@ func (ps podStatuses) Message() string {
// getPodsForDeletion receives resource info for a node, and returns all the pods from the given node that we // 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. // 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 []api.Pod, err error) { func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []corev1.Pod, err error) {
podList, err := o.client.Core().Pods(metav1.NamespaceAll).List(metav1.ListOptions{ podList, err := o.client.Core().Pods(metav1.NamespaceAll).List(metav1.ListOptions{
FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": nodeInfo.Name}).String()}) FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": nodeInfo.Name}).String()})
if err != nil { if err != nil {
...@@ -483,7 +482,7 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []api.P ...@@ -483,7 +482,7 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []api.P
} }
if len(fs) > 0 { if len(fs) > 0 {
return []api.Pod{}, errors.New(fs.Message()) return []corev1.Pod{}, errors.New(fs.Message())
} }
if len(ws) > 0 { if len(ws) > 0 {
fmt.Fprintf(o.ErrOut, "WARNING: %s\n", ws.Message()) fmt.Fprintf(o.ErrOut, "WARNING: %s\n", ws.Message())
...@@ -491,7 +490,7 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []api.P ...@@ -491,7 +490,7 @@ func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []api.P
return pods, nil return pods, nil
} }
func (o *DrainOptions) deletePod(pod api.Pod) error { func (o *DrainOptions) deletePod(pod corev1.Pod) error {
deleteOptions := &metav1.DeleteOptions{} deleteOptions := &metav1.DeleteOptions{}
if o.GracePeriodSeconds >= 0 { if o.GracePeriodSeconds >= 0 {
gracePeriodSeconds := int64(o.GracePeriodSeconds) gracePeriodSeconds := int64(o.GracePeriodSeconds)
...@@ -500,13 +499,13 @@ func (o *DrainOptions) deletePod(pod api.Pod) error { ...@@ -500,13 +499,13 @@ func (o *DrainOptions) deletePod(pod api.Pod) error {
return o.client.Core().Pods(pod.Namespace).Delete(pod.Name, deleteOptions) return o.client.Core().Pods(pod.Namespace).Delete(pod.Name, deleteOptions)
} }
func (o *DrainOptions) evictPod(pod api.Pod, policyGroupVersion string) error { func (o *DrainOptions) evictPod(pod corev1.Pod, policyGroupVersion string) error {
deleteOptions := &metav1.DeleteOptions{} deleteOptions := &metav1.DeleteOptions{}
if o.GracePeriodSeconds >= 0 { if o.GracePeriodSeconds >= 0 {
gracePeriodSeconds := int64(o.GracePeriodSeconds) gracePeriodSeconds := int64(o.GracePeriodSeconds)
deleteOptions.GracePeriodSeconds = &gracePeriodSeconds deleteOptions.GracePeriodSeconds = &gracePeriodSeconds
} }
eviction := &policy.Eviction{ eviction := &policyv1beta1.Eviction{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
APIVersion: policyGroupVersion, APIVersion: policyGroupVersion,
Kind: EvictionKind, Kind: EvictionKind,
...@@ -522,7 +521,7 @@ func (o *DrainOptions) evictPod(pod api.Pod, policyGroupVersion string) error { ...@@ -522,7 +521,7 @@ func (o *DrainOptions) evictPod(pod api.Pod, policyGroupVersion string) error {
} }
// deleteOrEvictPods deletes or evicts the pods on the api server // deleteOrEvictPods deletes or evicts the pods on the api server
func (o *DrainOptions) deleteOrEvictPods(pods []api.Pod) error { func (o *DrainOptions) deleteOrEvictPods(pods []corev1.Pod) error {
if len(pods) == 0 { if len(pods) == 0 {
return nil return nil
} }
...@@ -532,7 +531,7 @@ func (o *DrainOptions) deleteOrEvictPods(pods []api.Pod) error { ...@@ -532,7 +531,7 @@ func (o *DrainOptions) deleteOrEvictPods(pods []api.Pod) error {
return err return err
} }
getPodFn := func(namespace, name string) (*api.Pod, error) { getPodFn := func(namespace, name string) (*corev1.Pod, error) {
return o.client.Core().Pods(namespace).Get(name, metav1.GetOptions{}) return o.client.Core().Pods(namespace).Get(name, metav1.GetOptions{})
} }
...@@ -543,12 +542,12 @@ func (o *DrainOptions) deleteOrEvictPods(pods []api.Pod) error { ...@@ -543,12 +542,12 @@ func (o *DrainOptions) deleteOrEvictPods(pods []api.Pod) error {
} }
} }
func (o *DrainOptions) evictPods(pods []api.Pod, policyGroupVersion string, getPodFn func(namespace, name string) (*api.Pod, error)) error { func (o *DrainOptions) evictPods(pods []corev1.Pod, policyGroupVersion string, getPodFn func(namespace, name string) (*corev1.Pod, error)) error {
doneCh := make(chan bool, len(pods)) doneCh := make(chan bool, len(pods))
errCh := make(chan error, 1) errCh := make(chan error, 1)
for _, pod := range pods { for _, pod := range pods {
go func(pod api.Pod, doneCh chan bool, errCh chan error) { go func(pod corev1.Pod, doneCh chan bool, errCh chan error) {
var err error var err error
for { for {
err = o.evictPod(pod, policyGroupVersion) err = o.evictPod(pod, policyGroupVersion)
...@@ -564,7 +563,7 @@ func (o *DrainOptions) evictPods(pods []api.Pod, policyGroupVersion string, getP ...@@ -564,7 +563,7 @@ func (o *DrainOptions) evictPods(pods []api.Pod, policyGroupVersion string, getP
return return
} }
} }
podArray := []api.Pod{pod} podArray := []corev1.Pod{pod}
_, err = o.waitForDelete(podArray, kubectl.Interval, time.Duration(math.MaxInt64), true, getPodFn) _, err = o.waitForDelete(podArray, kubectl.Interval, time.Duration(math.MaxInt64), true, getPodFn)
if err == nil { if err == nil {
doneCh <- true doneCh <- true
...@@ -597,7 +596,7 @@ func (o *DrainOptions) evictPods(pods []api.Pod, policyGroupVersion string, getP ...@@ -597,7 +596,7 @@ func (o *DrainOptions) evictPods(pods []api.Pod, policyGroupVersion string, getP
} }
} }
func (o *DrainOptions) deletePods(pods []api.Pod, getPodFn func(namespace, name string) (*api.Pod, error)) error { func (o *DrainOptions) deletePods(pods []corev1.Pod, getPodFn func(namespace, name string) (*corev1.Pod, error)) error {
// 0 timeout means infinite, we use MaxInt64 to represent it. // 0 timeout means infinite, we use MaxInt64 to represent it.
var globalTimeout time.Duration var globalTimeout time.Duration
if o.Timeout == 0 { if o.Timeout == 0 {
...@@ -615,7 +614,7 @@ func (o *DrainOptions) deletePods(pods []api.Pod, getPodFn func(namespace, name ...@@ -615,7 +614,7 @@ func (o *DrainOptions) deletePods(pods []api.Pod, getPodFn func(namespace, name
return err return err
} }
func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Duration, usingEviction bool, getPodFn func(string, string) (*api.Pod, error)) ([]api.Pod, error) { func (o *DrainOptions) waitForDelete(pods []corev1.Pod, interval, timeout time.Duration, usingEviction bool, getPodFn func(string, string) (*corev1.Pod, error)) ([]corev1.Pod, error) {
var verbStr string var verbStr string
if usingEviction { if usingEviction {
verbStr = "evicted" verbStr = "evicted"
...@@ -623,7 +622,7 @@ func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Dura ...@@ -623,7 +622,7 @@ func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Dura
verbStr = "deleted" verbStr = "deleted"
} }
err := wait.PollImmediate(interval, timeout, func() (bool, error) { err := wait.PollImmediate(interval, timeout, func() (bool, error) {
pendingPods := []api.Pod{} pendingPods := []corev1.Pod{}
for i, pod := range pods { for i, pod := range pods {
p, err := getPodFn(pod.Namespace, pod.Name) p, err := getPodFn(pod.Namespace, pod.Name)
if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) { if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) {
...@@ -646,7 +645,7 @@ func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Dura ...@@ -646,7 +645,7 @@ func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Dura
// SupportEviction uses Discovery API to find out if the server support eviction subresource // SupportEviction uses Discovery API to find out if the server support eviction subresource
// If support, it will return its groupVersion; Otherwise, it will return "" // If support, it will return its groupVersion; Otherwise, it will return ""
func SupportEviction(clientset internalclientset.Interface) (string, error) { func SupportEviction(clientset kubernetes.Interface) (string, error) {
discoveryClient := clientset.Discovery() discoveryClient := clientset.Discovery()
groupList, err := discoveryClient.ServerGroups() groupList, err := discoveryClient.ServerGroups()
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment