package node import ( "errors" "fmt" "io" "github.com/spf13/cobra" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "github.com/openshift/origin/pkg/cmd/templates" "github.com/openshift/origin/pkg/cmd/util/clientcmd" ) const ManageNodeCommandName = "manage-node" var ( manageNodeLong = templates.LongDesc(` Manage nodes This command provides common operations on nodes for administrators. 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 pod on the provided nodes. list-pods: List all/selected pods on given/selected nodes. It can list the output in json/yaml format.`) manageNodeExample = templates.Examples(` # Block accepting any pods on given nodes %[1]s <mynode> --schedulable=false # Mark selected nodes as schedulable %[1]s --selector="<env=dev>" --schedulable=true # Migrate selected pods %[1]s <mynode> --evacuate --pod-selector="<service=myapp>" # Migrate selected pods, use a grace period of 60 seconds %[1]s <mynode> --evacuate --grace-period=60 --pod-selector="<service=myapp>" # Migrate selected pods not backed by replication controller %[1]s <mynode> --evacuate --force --pod-selector="<service=myapp>" # Show pods that will be migrated %[1]s <mynode> --evacuate --dry-run --pod-selector="<service=myapp>" # List all pods on given nodes %[1]s <mynode1> <mynode2> --list-pods`) ) var schedulable, evacuate, listpods bool // NewCommandManageNode implements the OpenShift cli manage-node command func NewCommandManageNode(f *clientcmd.Factory, commandName, fullName string, out, errout io.Writer) *cobra.Command { opts := &NodeOptions{} schedulableOp := &SchedulableOptions{Options: opts} evacuateOp := NewEvacuateOptions(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, errout); 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 }