github.com/anuvu/nomad@v0.8.7-atom1/command/node_eligibility.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api/contexts"
     8  	"github.com/posener/complete"
     9  )
    10  
    11  type NodeEligibilityCommand struct {
    12  	Meta
    13  }
    14  
    15  func (c *NodeEligibilityCommand) Help() string {
    16  	helpText := `
    17  Usage: nomad node eligibility [options] <node>
    18  
    19    Toggles the nodes scheduling eligibility. When a node is marked as ineligible,
    20    no new allocations will be placed on it but existing allocations will remain.
    21    To remove existing allocations, use the node drain command.
    22  
    23    It is required that either -enable or -disable is specified, but not both.
    24    The -self flag is useful to set the scheduling eligibility of the local node.
    25  
    26  General Options:
    27  
    28    ` + generalOptionsUsage() + `
    29  
    30  Node Eligibility Options:
    31  
    32    -disable
    33      Mark the specified node as ineligible for new allocations.
    34  
    35    -enable
    36      Mark the specified node as eligible for new allocations.
    37  
    38    -self
    39      Set the eligibility of the local node.
    40  `
    41  	return strings.TrimSpace(helpText)
    42  }
    43  
    44  func (c *NodeEligibilityCommand) Synopsis() string {
    45  	return "Toggle scheduling eligibility for a given node"
    46  }
    47  
    48  func (c *NodeEligibilityCommand) AutocompleteFlags() complete.Flags {
    49  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    50  		complete.Flags{
    51  			"-disable": complete.PredictNothing,
    52  			"-enable":  complete.PredictNothing,
    53  			"-self":    complete.PredictNothing,
    54  		})
    55  }
    56  
    57  func (c *NodeEligibilityCommand) AutocompleteArgs() complete.Predictor {
    58  	return complete.PredictFunc(func(a complete.Args) []string {
    59  		client, err := c.Meta.Client()
    60  		if err != nil {
    61  			return nil
    62  		}
    63  
    64  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Nodes, nil)
    65  		if err != nil {
    66  			return []string{}
    67  		}
    68  		return resp.Matches[contexts.Nodes]
    69  	})
    70  }
    71  
    72  func (c *NodeEligibilityCommand) Name() string { return "node-eligibility" }
    73  
    74  func (c *NodeEligibilityCommand) Run(args []string) int {
    75  	var enable, disable, self bool
    76  
    77  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    78  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    79  	flags.BoolVar(&enable, "enable", false, "Mark node as eligibile for scheduling")
    80  	flags.BoolVar(&disable, "disable", false, "Mark node as ineligibile for scheduling")
    81  	flags.BoolVar(&self, "self", false, "")
    82  
    83  	if err := flags.Parse(args); err != nil {
    84  		return 1
    85  	}
    86  
    87  	// Check that we got either enable or disable, but not both.
    88  	if (enable && disable) || (!enable && !disable) {
    89  		c.Ui.Error("Ethier the '-enable' or '-disable' flag must be set")
    90  		c.Ui.Error(commandErrorText(c))
    91  		return 1
    92  	}
    93  
    94  	// Check that we got a node ID
    95  	args = flags.Args()
    96  	if l := len(args); self && l != 0 || !self && l != 1 {
    97  		c.Ui.Error("Node ID must be specified if -self isn't being used")
    98  		c.Ui.Error(commandErrorText(c))
    99  		return 1
   100  	}
   101  
   102  	// Get the HTTP client
   103  	client, err := c.Meta.Client()
   104  	if err != nil {
   105  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   106  		return 1
   107  	}
   108  
   109  	// If -self flag is set then determine the current node.
   110  	var nodeID string
   111  	if !self {
   112  		nodeID = args[0]
   113  	} else {
   114  		var err error
   115  		if nodeID, err = getLocalNodeID(client); err != nil {
   116  			c.Ui.Error(err.Error())
   117  			return 1
   118  		}
   119  	}
   120  
   121  	// Check if node exists
   122  	if len(nodeID) == 1 {
   123  		c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
   124  		return 1
   125  	}
   126  
   127  	nodeID = sanitizeUUIDPrefix(nodeID)
   128  	nodes, _, err := client.Nodes().PrefixList(nodeID)
   129  	if err != nil {
   130  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   131  		return 1
   132  	}
   133  	// Return error if no nodes are found
   134  	if len(nodes) == 0 {
   135  		c.Ui.Error(fmt.Sprintf("No node(s) with prefix or id %q found", nodeID))
   136  		return 1
   137  	}
   138  	if len(nodes) > 1 {
   139  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple nodes\n\n%s",
   140  			formatNodeStubList(nodes, true)))
   141  		return 1
   142  	}
   143  
   144  	// Prefix lookup matched a single node
   145  	node, _, err := client.Nodes().Info(nodes[0].ID, nil)
   146  	if err != nil {
   147  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   148  		return 1
   149  	}
   150  
   151  	// Toggle node eligibility
   152  	if _, err := client.Nodes().ToggleEligibility(node.ID, enable, nil); err != nil {
   153  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   154  		return 1
   155  	}
   156  
   157  	if enable {
   158  		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: eligible for scheduling", node.ID))
   159  	} else {
   160  		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: ineligible for scheduling", node.ID))
   161  	}
   162  	return 0
   163  }