package node import ( "errors" "fmt" "io" "github.com/spf13/cobra" kcmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/openshift/origin/pkg/cmd/util/clientcmd" ) const ( ManageNodeCommandName = "manage-node" manageNodeLong = `Manage node operations schedulable: Marking node schedulable will allow pods to be schedulable on the node and marking node unschedulable will block pods to be scheduled on the node. evacuate: Migrate all/selected pods. There is an option to delete the bare pods. It can list all pods that will be migrated before performing evacuation. list-pods: List all/selected pods on given/selected nodes. It can list the output in json/yaml format.` manageNodeExample = ` // Block accepting any pods on given nodes $ %[1]s --schedulable=false // Mark selected nodes as schedulable $ %[1]s --selector="" --schedulable=true // Migrate selected pods $ %[1]s --evacuate --pod-selector="" // Show pods that will be migrated $ %[1]s --evacuate --dry-run --pod-selector="" // List all pods on given nodes $ %[1]s --list-pods` ) var schedulable, evacuate, listpods bool func NewCommandManageNode(f *clientcmd.Factory, commandName, fullName string, out io.Writer) *cobra.Command { opts := &NodeOptions{} schedulableOp := &SchedulableOptions{Options: opts} evacuateOp := &EvacuateOptions{Options: opts} listpodsOp := &ListPodsOptions{Options: opts} cmd := &cobra.Command{ Use: commandName, Short: "Manage nodes - list pods, evacuate, or mark ready", Long: manageNodeLong, Example: fmt.Sprintf(manageNodeExample, fullName), Run: func(c *cobra.Command, args []string) { if err := ValidOperation(c); err != nil { kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) } if err := opts.Complete(f, c, args, out); err != nil { kcmdutil.CheckErr(err) } checkNodeSelector := c.Flag("selector").Changed if err := opts.Validate(checkNodeSelector); err != nil { kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) } // Cross op validations if evacuateOp.DryRun && !evacuate { err := errors.New("--dry-run is only applicable for --evacuate") kcmdutil.CheckErr(kcmdutil.UsageError(c, err.Error())) } var err error if c.Flag("schedulable").Changed { schedulableOp.Schedulable = schedulable err = schedulableOp.Run() } else if evacuate { err = evacuateOp.Run() } else if listpods { err = listpodsOp.Run() } kcmdutil.CheckErr(err) }, } flags := cmd.Flags() // Supported operations flags.BoolVar(&schedulable, "schedulable", false, "Control pod schedulability on the node.") flags.BoolVar(&evacuate, "evacuate", false, "Migrate all/selected pods on the node.") flags.BoolVar(&listpods, "list-pods", false, "List all/selected pods on the node. Printer flags --output, etc. are only valid for this option.") // Common optional params flags.StringVar(&opts.PodSelector, "pod-selector", "", "Label selector to filter pods on the node. Optional param for --evacuate or --list-pods") flags.StringVar(&opts.Selector, "selector", "", "Label selector to filter nodes. Either pass one/more nodes as arguments or use this node selector") // Operation specific params evacuateOp.AddFlags(cmd) listpodsOp.AddFlags(cmd) return cmd } func ValidOperation(c *cobra.Command) error { numOps := 0 if c.Flag("schedulable").Changed { numOps++ } if evacuate { numOps++ } if listpods { numOps++ } if numOps == 0 { return errors.New("must provide a node operation. Supported operations: --schedulable, --evacuate and --list-pods") } else if numOps != 1 { return errors.New("must provide only one node operation at a time") } return nil }