github.com/djenriquez/nomad-1@v0.8.1/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) Run(args []string) int {
    73  	var enable, disable, self bool
    74  
    75  	flags := c.Meta.FlagSet("node-eligibility", FlagSetClient)
    76  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    77  	flags.BoolVar(&enable, "enable", false, "Mark node as eligibile for scheduling")
    78  	flags.BoolVar(&disable, "disable", false, "Mark node as ineligibile for scheduling")
    79  	flags.BoolVar(&self, "self", false, "")
    80  
    81  	if err := flags.Parse(args); err != nil {
    82  		return 1
    83  	}
    84  
    85  	// Check that we got either enable or disable, but not both.
    86  	if (enable && disable) || (!enable && !disable) {
    87  		c.Ui.Error(c.Help())
    88  		return 1
    89  	}
    90  
    91  	// Check that we got a node ID
    92  	args = flags.Args()
    93  	if l := len(args); self && l != 0 || !self && l != 1 {
    94  		c.Ui.Error("Node ID must be specified if -self isn't being used")
    95  		return 1
    96  	}
    97  
    98  	// Get the HTTP client
    99  	client, err := c.Meta.Client()
   100  	if err != nil {
   101  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   102  		return 1
   103  	}
   104  
   105  	// If -self flag is set then determine the current node.
   106  	var nodeID string
   107  	if !self {
   108  		nodeID = args[0]
   109  	} else {
   110  		var err error
   111  		if nodeID, err = getLocalNodeID(client); err != nil {
   112  			c.Ui.Error(err.Error())
   113  			return 1
   114  		}
   115  	}
   116  
   117  	// Check if node exists
   118  	if len(nodeID) == 1 {
   119  		c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
   120  		return 1
   121  	}
   122  
   123  	nodeID = sanitizeUUIDPrefix(nodeID)
   124  	nodes, _, err := client.Nodes().PrefixList(nodeID)
   125  	if err != nil {
   126  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   127  		return 1
   128  	}
   129  	// Return error if no nodes are found
   130  	if len(nodes) == 0 {
   131  		c.Ui.Error(fmt.Sprintf("No node(s) with prefix or id %q found", nodeID))
   132  		return 1
   133  	}
   134  	if len(nodes) > 1 {
   135  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple nodes\n\n%s",
   136  			formatNodeStubList(nodes, true)))
   137  		return 1
   138  	}
   139  
   140  	// Prefix lookup matched a single node
   141  	node, _, err := client.Nodes().Info(nodes[0].ID, nil)
   142  	if err != nil {
   143  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   144  		return 1
   145  	}
   146  
   147  	// Toggle node eligibility
   148  	if _, err := client.Nodes().ToggleEligibility(node.ID, enable, nil); err != nil {
   149  		c.Ui.Error(fmt.Sprintf("Error updating scheduling eligibility: %s", err))
   150  		return 1
   151  	}
   152  
   153  	if enable {
   154  		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: eligible for scheduling", node.ID))
   155  	} else {
   156  		c.Ui.Output(fmt.Sprintf("Node %q scheduling eligibility set: ineligible for scheduling", node.ID))
   157  	}
   158  	return 0
   159  }