UNPKG

6.31 kBtext/coffeescriptView Raw
1#===============================================================================
2# PandaCluster - Awesome Command-Line Tool and Library to Manage CoreOS Clusters
3#===============================================================================
4# This file specifies the Command-Line Interface for PandaCluster. When used as
5# a command-line tool, we still call PandaCluster functions, but we have to build
6# the "options" object for each method by parsing command-line arguments.
7#===============================================================================
8# Modules
9#===============================================================================
10{argv} = process
11{resolve} = require "path"
12{read, write, remove} = require "fairmont" # Awesome utility functions.
13{parse} = require "c50n" # Awesome .cson file parsing
14
15{call} = require "when/generator"
16
17# Awesome manipulations in the functional style.
18{pluck, where, flatten} = require "underscore"
19
20# Access PandaCluster!!
21PC = require "./pbx"
22
23
24#===============================================================================
25# Helper Fucntions
26#===============================================================================
27# Wrap parseInt - hardcode the radix at 10 to avoid confusion
28# See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
29is_integer = (value) -> parseInt(value, 10) != NaN
30
31# Output an Info Blurb and optional message.
32usage = (entry, message) ->
33 if message?
34 throw "#{message}\n" + read( resolve( __dirname, "../", "docs", entry ) )
35 else
36 throw read( resolve( __dirname, "..", "docs", entry ) )
37
38# Accept only the allowed values for flags that take an enumerated type.
39allow_only = (allowed_values, value, flag) ->
40 unless value in allowed_values
41 throw "\nError: Only Allowed Values May Be Specified For Flag: #{flag}\n\n"
42
43# Accept only integers within the accepted range, inclusive.
44allow_between = (min, max, value, flag) ->
45 unless is_integer value
46 throw "\nError: Value Must Be An Integer For Flag: #{flag}\n\n"
47
48 unless min <= value <= max
49 throw "\nError: Value Is Outside Allowed Range For Flag: #{flag}\n\n"
50
51# Parse the arguments passed to a sub-command. Construct an "options" object to pass to the main library.
52parse_cli = (command, argv) ->
53 # Deliver an info blurb if neccessary.
54 usage command if argv[0] == "-h" || argv[0] == "help"
55
56 # Begin constructing the "options" object by pulling persistent configuration data
57 # from the CSON file in the user's $HOME directory.
58 options = parse( read( resolve("#{process.env.HOME}/.pandacluster.cson")))
59
60 # Extract flag data from the argument definition for this sub-command.
61 definitions = parse( read( resolve( __dirname, "arguments.cson")))
62 cmd_def = definitions[command] # Produces an array of objects describing this single sub-command.
63 flags = pluck cmd_def, "flag"
64 required_flags = pluck( where( cmd_def, {required: true}), "flag" )
65
66 # Loop over arguments. Collect settings into "options" and validate where possible.
67 while argv.length > 0
68 # Check to see if the entered flag is valid.
69 if flags.indexOf(argv[0]) == -1
70 usage command, "\nError: Unrecognized Flag Provided: #{argv[0]}\n"
71 # Check to see if there is a "dangling" flag that has no content provided.
72 if argv.length == 1
73 usage command, "\nError: Valid Flag Provided But Not Defined: #{argv[0]}\n"
74
75 # Validate the argument against its defintion.
76 {name, type, required, allowed_values, min, max} = cmd_def[ flags.indexOf(argv[0]) ]
77
78 allow_only( allowed_values, argv[1], argv[0]) if allowed_values?
79 allow_between( min, max, argv[1], argv[0]) if min? and max?
80 remove( required_flags, argv[0]) if required? == true
81
82 # Add data to the "options" object.
83 options[name] = argv[1]
84
85 # Delete these two arguments.
86 argv = argv[2..]
87
88 options
89
90 # Done looping. Check to see if all required flags have been defined.
91 unless required_flags.length == 0
92 usage command, "\nError: Mandatory Flag(s) Remain Undefined: #{required_flags}\n"
93
94 # Parsing complete. Return the completed "options" object.
95 return options
96
97
98#===============================================================================
99# Main - Top-Level Command-Line Interface
100#===============================================================================
101# Chop off the argument array so that only the useful arguments remain.
102argv = argv[2..]
103
104# Deliver an info blurb if neccessary.
105if argv.length == 0 || argv[0] == "-h" || argv[0] == "help"
106 usage "main"
107
108# Now, look for the specified sub-command.
109
110call ->
111 try
112 switch argv[0]
113
114 when "cluster"
115 switch argv[1]
116 when "create"
117 options = parse_cli "create_cluster", argv[2..]
118 console.log "*****cluster create args: ", options
119 res = (yield PC.create_cluster options)
120 console.log "*****cluster create results: ", res
121 when "delete"
122 options = parse_cli "delete_cluster", argv[2..]
123 console.log "*****cluster delete args: ", options
124 res = (yield PC.delete_cluster options)
125 console.log "*****cluster delete results: ", res
126 when "wait"
127 options = parse_cli "wait_on_cluster", argv[2..]
128 console.log "*****waiting on cluster args: ", options
129 res = (yield PC.wait_on_cluster options)
130 console.log "*****cluster wait results: ", res
131 else
132 # When the command cannot be identified, display the help guide.
133 usage "main", "\nError: Command Not Found: #{argv[1]} \n"
134
135 when "user"
136 switch argv[1]
137 when "create"
138 options = parse_cli "create_user", argv[2..]
139 console.log "*****user create args: ", options
140 res = (yield PC.create_user options)
141 console.log "*****user create results: ", res
142 else
143 # When the command cannot be identified, display the help guide.
144 usage "main", "\nError: Command Not Found: #{argv[1]} \n"
145
146 else
147 # When the command cannot be identified, display the help guide.
148 usage "main", "\nError: Command Not Found: #{argv[0]} \n"
149 catch error
150 throw error