mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
kubectl drain: make code reusable
DrainOptions requires a few fields to be set, and the expectation is that these are set as part of construction of the object. If they are set, then the drain code can be reused in other kubernetes projects. This does not create a contract that DrainOptions should fulfill going forwards, any more than any of the other types that happen to be exposed are part of the contract. Instead, this merely makes use outside the package possible.
This commit is contained in:
parent
59735fb908
commit
72afd143c4
@ -49,7 +49,7 @@ import (
|
|||||||
type DrainOptions struct {
|
type DrainOptions struct {
|
||||||
client *internalclientset.Clientset
|
client *internalclientset.Clientset
|
||||||
restClient *restclient.RESTClient
|
restClient *restclient.RESTClient
|
||||||
factory cmdutil.Factory
|
Factory cmdutil.Factory
|
||||||
Force bool
|
Force bool
|
||||||
GracePeriodSeconds int
|
GracePeriodSeconds int
|
||||||
IgnoreDaemonsets bool
|
IgnoreDaemonsets bool
|
||||||
@ -58,8 +58,8 @@ type DrainOptions struct {
|
|||||||
DeleteLocalData bool
|
DeleteLocalData bool
|
||||||
mapper meta.RESTMapper
|
mapper meta.RESTMapper
|
||||||
nodeInfo *resource.Info
|
nodeInfo *resource.Info
|
||||||
out io.Writer
|
Out io.Writer
|
||||||
errOut io.Writer
|
ErrOut io.Writer
|
||||||
typer runtime.ObjectTyper
|
typer runtime.ObjectTyper
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdCordon(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
func NewCmdCordon(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
options := &DrainOptions{factory: f, out: out}
|
options := &DrainOptions{Factory: f, Out: out}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "cordon NODE",
|
Use: "cordon NODE",
|
||||||
@ -121,7 +121,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdUncordon(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
func NewCmdUncordon(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
options := &DrainOptions{factory: f, out: out}
|
options := &DrainOptions{Factory: f, Out: out}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "uncordon NODE",
|
Use: "uncordon NODE",
|
||||||
@ -170,7 +170,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||||
options := &DrainOptions{factory: f, out: out, errOut: errOut, backOff: clockwork.NewRealClock()}
|
options := &DrainOptions{Factory: f, Out: out, ErrOut: errOut, backOff: clockwork.NewRealClock()}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "drain NODE",
|
Use: "drain NODE",
|
||||||
@ -198,23 +198,23 @@ func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error {
|
|||||||
return cmdutil.UsageError(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use))
|
return cmdutil.UsageError(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use))
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.client, err = o.factory.ClientSet(); err != nil {
|
if o.client, err = o.Factory.ClientSet(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
o.restClient, err = o.factory.RESTClient()
|
o.restClient, err = o.Factory.RESTClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
o.mapper, o.typer = o.factory.Object()
|
o.mapper, o.typer = o.Factory.Object()
|
||||||
|
|
||||||
cmdNamespace, _, err := o.factory.DefaultNamespace()
|
cmdNamespace, _, err := o.Factory.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := o.factory.NewBuilder().
|
r := o.Factory.NewBuilder().
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
ResourceNames("node", args[0]).
|
ResourceNames("node", args[0]).
|
||||||
Do()
|
Do()
|
||||||
@ -240,7 +240,7 @@ func (o *DrainOptions) RunDrain() error {
|
|||||||
|
|
||||||
err := o.deleteOrEvictPodsSimple()
|
err := o.deleteOrEvictPodsSimple()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cmdutil.PrintSuccess(o.mapper, false, o.out, "node", o.nodeInfo.Name, false, "drained")
|
cmdutil.PrintSuccess(o.mapper, false, o.Out, "node", o.nodeInfo.Name, false, "drained")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -257,9 +257,9 @@ func (o *DrainOptions) deleteOrEvictPodsSimple() error {
|
|||||||
if newErr != nil {
|
if newErr != nil {
|
||||||
return newErr
|
return newErr
|
||||||
}
|
}
|
||||||
fmt.Fprintf(o.errOut, "There are pending pods when an error occurred: %v\n", err)
|
fmt.Fprintf(o.ErrOut, "There are pending pods when an error occurred: %v\n", err)
|
||||||
for _, pendingPod := range pendingPods {
|
for _, pendingPod := range pendingPods {
|
||||||
fmt.Fprintf(o.errOut, "%s/%s\n", "pod", pendingPod.Name)
|
fmt.Fprintf(o.ErrOut, "%s/%s\n", "pod", pendingPod.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -288,7 +288,7 @@ func (o *DrainOptions) getPodCreator(pod api.Pod) (*api.SerializedReference, err
|
|||||||
}
|
}
|
||||||
// Now verify that the specified creator actually exists.
|
// Now verify that the specified creator actually exists.
|
||||||
sr := &api.SerializedReference{}
|
sr := &api.SerializedReference{}
|
||||||
if err := runtime.DecodeInto(o.factory.Decoder(true), []byte(creatorRef), sr); err != nil {
|
if err := runtime.DecodeInto(o.Factory.Decoder(true), []byte(creatorRef), sr); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// We assume the only reason for an error is because the controller is
|
// We assume the only reason for an error is because the controller is
|
||||||
@ -413,7 +413,7 @@ func (o *DrainOptions) getPodsForDeletion() (pods []api.Pod, err error) {
|
|||||||
return []api.Pod{}, errors.New(fs.Message())
|
return []api.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())
|
||||||
}
|
}
|
||||||
return pods, nil
|
return pods, nil
|
||||||
}
|
}
|
||||||
@ -551,7 +551,7 @@ func (o *DrainOptions) waitForDelete(pods []api.Pod, interval, timeout time.Dura
|
|||||||
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) {
|
||||||
cmdutil.PrintSuccess(o.mapper, false, o.out, "pod", pod.Name, false, verbStr)
|
cmdutil.PrintSuccess(o.mapper, false, o.Out, "pod", pod.Name, false, verbStr)
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -603,7 +603,7 @@ func SupportEviction(clientset *internalclientset.Clientset) (string, error) {
|
|||||||
// RunCordonOrUncordon runs either Cordon or Uncordon. The desired value for
|
// RunCordonOrUncordon runs either Cordon or Uncordon. The desired value for
|
||||||
// "Unschedulable" is passed as the first arg.
|
// "Unschedulable" is passed as the first arg.
|
||||||
func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
|
func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
|
||||||
cmdNamespace, _, err := o.factory.DefaultNamespace()
|
cmdNamespace, _, err := o.Factory.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
|
|||||||
if o.nodeInfo.Mapping.GroupVersionKind.Kind == "Node" {
|
if o.nodeInfo.Mapping.GroupVersionKind.Kind == "Node" {
|
||||||
unsched := reflect.ValueOf(o.nodeInfo.Object).Elem().FieldByName("Spec").FieldByName("Unschedulable")
|
unsched := reflect.ValueOf(o.nodeInfo.Object).Elem().FieldByName("Spec").FieldByName("Unschedulable")
|
||||||
if unsched.Bool() == desired {
|
if unsched.Bool() == desired {
|
||||||
cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, already(desired))
|
cmdutil.PrintSuccess(o.mapper, false, o.Out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, already(desired))
|
||||||
} else {
|
} else {
|
||||||
helper := resource.NewHelper(o.restClient, o.nodeInfo.Mapping)
|
helper := resource.NewHelper(o.restClient, o.nodeInfo.Mapping)
|
||||||
unsched.SetBool(desired)
|
unsched.SetBool(desired)
|
||||||
@ -633,10 +633,10 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, changed(desired))
|
cmdutil.PrintSuccess(o.mapper, false, o.Out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, changed(desired))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, "skipped")
|
cmdutil.PrintSuccess(o.mapper, false, o.Out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, false, "skipped")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -682,7 +682,7 @@ func TestDeletePods(t *testing.T) {
|
|||||||
f, _, _, _ := cmdtesting.NewAPIFactory()
|
f, _, _, _ := cmdtesting.NewAPIFactory()
|
||||||
o := DrainOptions{}
|
o := DrainOptions{}
|
||||||
o.mapper, _ = f.Object()
|
o.mapper, _ = f.Object()
|
||||||
o.out = os.Stdout
|
o.Out = os.Stdout
|
||||||
_, pods := createPods(false)
|
_, pods := createPods(false)
|
||||||
pendingPods, err := o.waitForDelete(pods, test.interval, test.timeout, false, test.getPodFn)
|
pendingPods, err := o.waitForDelete(pods, test.interval, test.timeout, false, test.getPodFn)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user