mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-04 23:17:50 +00:00
Merge pull request #48082 from ravisantoshgudimetla/kubectl_drain_node_conversion
Automatic merge from submit-queue (batch tested with PRs 48082, 48815, 48901, 48824) Changes for typecasting node in drain **What this PR does / why we need it**: **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #48059 **Special notes for your reviewer**: Precursor to #44944 **Release note**: ```release-note kubectl drain now uses PATCH instead of PUT to update the node. The node object is now of type v1 instead of using internal api. ```
This commit is contained in:
@@ -20,8 +20,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -34,8 +34,11 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
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"
|
||||
@@ -84,7 +87,6 @@ const (
|
||||
kLocalStorageWarning = "Deleting pods with local storage"
|
||||
kUnmanagedFatal = "pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet (use --force to override)"
|
||||
kUnmanagedWarning = "Deleting pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet"
|
||||
kMaxNodeUpdateRetry = 10
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -621,27 +623,28 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
|
||||
}
|
||||
|
||||
if o.nodeInfo.Mapping.GroupVersionKind.Kind == "Node" {
|
||||
unsched := reflect.ValueOf(o.nodeInfo.Object).Elem().FieldByName("Spec").FieldByName("Unschedulable")
|
||||
if unsched.Bool() == desired {
|
||||
obj, err := o.nodeInfo.Mapping.ConvertToVersion(o.nodeInfo.Object, o.nodeInfo.Mapping.GroupVersionKind.GroupVersion())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldData, err := json.Marshal(obj)
|
||||
node, ok := obj.(*corev1.Node)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected Type%T, expected Node", obj)
|
||||
}
|
||||
unsched := node.Spec.Unschedulable
|
||||
if unsched == desired {
|
||||
cmdutil.PrintSuccess(o.mapper, false, o.Out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, already(desired))
|
||||
} else {
|
||||
helper := resource.NewHelper(o.restClient, o.nodeInfo.Mapping)
|
||||
unsched.SetBool(desired)
|
||||
node.Spec.Unschedulable = desired
|
||||
var err error
|
||||
for i := 0; i < kMaxNodeUpdateRetry; i++ {
|
||||
// We don't care about what previous versions may exist, we always want
|
||||
// to overwrite, and Replace always sets current ResourceVersion if version is "".
|
||||
helper.Versioner.SetResourceVersion(o.nodeInfo.Object, "")
|
||||
_, err = helper.Replace(cmdNamespace, o.nodeInfo.Name, true, o.nodeInfo.Object)
|
||||
if err != nil {
|
||||
if !apierrors.IsConflict(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
// It's a race, no need to sleep
|
||||
newData, err := json.Marshal(obj)
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = helper.Patch(cmdNamespace, o.nodeInfo.Name, types.StrategicMergePatchType, patchBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user