morpheus-cli 2.10.3 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/morpheus +5 -96
- data/lib/morpheus/api/api_client.rb +23 -1
- data/lib/morpheus/api/checks_interface.rb +106 -0
- data/lib/morpheus/api/incidents_interface.rb +102 -0
- data/lib/morpheus/api/monitoring_apps_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_contacts_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_groups_interface.rb +47 -0
- data/lib/morpheus/api/monitoring_interface.rb +36 -0
- data/lib/morpheus/api/option_type_lists_interface.rb +47 -0
- data/lib/morpheus/api/option_types_interface.rb +47 -0
- data/lib/morpheus/api/roles_interface.rb +0 -1
- data/lib/morpheus/api/setup_interface.rb +19 -9
- data/lib/morpheus/cli.rb +20 -1
- data/lib/morpheus/cli/accounts.rb +8 -3
- data/lib/morpheus/cli/app_templates.rb +19 -11
- data/lib/morpheus/cli/apps.rb +52 -37
- data/lib/morpheus/cli/cli_command.rb +229 -53
- data/lib/morpheus/cli/cli_registry.rb +48 -40
- data/lib/morpheus/cli/clouds.rb +55 -26
- data/lib/morpheus/cli/command_error.rb +12 -0
- data/lib/morpheus/cli/credentials.rb +68 -26
- data/lib/morpheus/cli/curl_command.rb +98 -0
- data/lib/morpheus/cli/dashboard_command.rb +2 -7
- data/lib/morpheus/cli/deployments.rb +4 -4
- data/lib/morpheus/cli/deploys.rb +1 -2
- data/lib/morpheus/cli/dot_file.rb +5 -8
- data/lib/morpheus/cli/error_handler.rb +179 -15
- data/lib/morpheus/cli/groups.rb +21 -13
- data/lib/morpheus/cli/hosts.rb +220 -110
- data/lib/morpheus/cli/instance_types.rb +2 -2
- data/lib/morpheus/cli/instances.rb +257 -167
- data/lib/morpheus/cli/key_pairs.rb +15 -9
- data/lib/morpheus/cli/library.rb +673 -27
- data/lib/morpheus/cli/license.rb +2 -2
- data/lib/morpheus/cli/load_balancers.rb +4 -4
- data/lib/morpheus/cli/log_level_command.rb +6 -4
- data/lib/morpheus/cli/login.rb +17 -3
- data/lib/morpheus/cli/logout.rb +25 -11
- data/lib/morpheus/cli/man_command.rb +388 -0
- data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/monitoring_helper.rb +434 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +620 -112
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
- data/lib/morpheus/cli/monitoring_apps_command.rb +29 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +427 -0
- data/lib/morpheus/cli/monitoring_contacts_command.rb +373 -0
- data/lib/morpheus/cli/monitoring_groups_command.rb +29 -0
- data/lib/morpheus/cli/monitoring_incidents_command.rb +711 -0
- data/lib/morpheus/cli/option_types.rb +10 -1
- data/lib/morpheus/cli/recent_activity_command.rb +2 -5
- data/lib/morpheus/cli/remote.rb +874 -134
- data/lib/morpheus/cli/roles.rb +54 -27
- data/lib/morpheus/cli/security_group_rules.rb +2 -2
- data/lib/morpheus/cli/security_groups.rb +23 -19
- data/lib/morpheus/cli/set_prompt_command.rb +50 -0
- data/lib/morpheus/cli/shell.rb +222 -157
- data/lib/morpheus/cli/tasks.rb +19 -15
- data/lib/morpheus/cli/users.rb +27 -17
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +28 -13
- data/lib/morpheus/cli/whoami.rb +131 -52
- data/lib/morpheus/cli/workflows.rb +24 -9
- data/lib/morpheus/formatters.rb +195 -3
- data/lib/morpheus/logging.rb +86 -0
- data/lib/morpheus/terminal.rb +371 -0
- data/scripts/generate_morpheus_commands_help.morpheus +60 -0
- metadata +21 -2
@@ -1,13 +1,17 @@
|
|
1
|
+
require 'morpheus/logging'
|
1
2
|
require 'morpheus/cli/option_parser'
|
2
3
|
require 'morpheus/cli/cli_registry'
|
3
4
|
require 'morpheus/cli/mixins/print_helper'
|
4
5
|
require 'morpheus/cli/credentials'
|
5
6
|
require 'morpheus/api/api_client'
|
6
7
|
require 'morpheus/cli/remote'
|
8
|
+
require 'morpheus/terminal'
|
7
9
|
|
8
10
|
module Morpheus
|
9
11
|
module Cli
|
10
12
|
# Module to be included by every CLI command so that commands get registered
|
13
|
+
# This mixin defines a print and puts method, and delegates
|
14
|
+
# todo: use delegate
|
11
15
|
module CliCommand
|
12
16
|
|
13
17
|
def self.included(klass)
|
@@ -21,17 +25,75 @@ module Morpheus
|
|
21
25
|
# this setting makes it easy for the called to disable prompting
|
22
26
|
attr_reader :no_prompt
|
23
27
|
|
24
|
-
#
|
25
|
-
def
|
26
|
-
@
|
27
|
-
|
28
|
+
# @return [Morpheus::Terminal] the terminal this command is being executed inside of
|
29
|
+
def my_terminal
|
30
|
+
@my_terminal ||= Morpheus::Terminal.instance
|
31
|
+
end
|
32
|
+
|
33
|
+
# set the terminal this is running this command.
|
34
|
+
# @param term [MorpheusTerminal] the terminal this command is assigned to
|
35
|
+
# @return the Terminal this command is being executed inside of
|
36
|
+
def my_terminal=(term)
|
37
|
+
if !t.is_a?(Morpheus::Terminal)
|
38
|
+
raise "CliCommand #{self.class} terminal= expects object of type Terminal and instead got a #{t.class}"
|
39
|
+
end
|
40
|
+
@my_terminal = t
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# delegate :print, to: :my_terminal
|
45
|
+
# delegate :puts, to: :my_terminal
|
46
|
+
# or . . . bum bum bummm
|
47
|
+
# a paradigm shift away from include and use module functions instead.
|
48
|
+
# module_function :print, puts
|
49
|
+
# delegate :puts, to: :my_terminal
|
50
|
+
|
51
|
+
def print(*msgs)
|
52
|
+
my_terminal.stdout.print(*msgs)
|
53
|
+
end
|
54
|
+
|
55
|
+
def puts(*msgs)
|
56
|
+
my_terminal.stdout.puts(*msgs)
|
57
|
+
end
|
58
|
+
|
59
|
+
def print_error(*msgs)
|
60
|
+
my_terminal.stderr.print(*msgs)
|
61
|
+
end
|
62
|
+
|
63
|
+
def puts_error(*msgs)
|
64
|
+
my_terminal.stderr.puts(*msgs)
|
28
65
|
end
|
29
66
|
|
67
|
+
# todo: use terminal.stdin
|
68
|
+
# def readline(*msgs)
|
69
|
+
# @my_terminal.stdin.readline(*msgs)
|
70
|
+
# end
|
71
|
+
|
72
|
+
# todo: maybe...
|
73
|
+
# disabled prompting for this command
|
74
|
+
# def noninteractive()
|
75
|
+
# @no_prompt = true
|
76
|
+
# self
|
77
|
+
# end
|
78
|
+
|
30
79
|
# whether to prompt or not, this is true by default.
|
31
80
|
def interactive?
|
32
81
|
@no_prompt != true
|
33
82
|
end
|
34
83
|
|
84
|
+
def raise_command_error(msg)
|
85
|
+
raise Morpheus::Cli::CommandError.new(msg)
|
86
|
+
end
|
87
|
+
|
88
|
+
# parse_id_list splits returns the given id_list with its values split on a comma
|
89
|
+
# your id values cannot contain a comma, atm...
|
90
|
+
# @param id_list [String or Array of Strings]
|
91
|
+
# @param delim [String] Default is a comma and any surrounding white space.
|
92
|
+
# @return array of values
|
93
|
+
def parse_id_list(id_list, delim=/\s*\,\s*/)
|
94
|
+
[id_list].flatten.collect {|it| it ? it.to_s.split(delim) : nil }.flatten.compact
|
95
|
+
end
|
96
|
+
|
35
97
|
# Appends Array of OptionType definitions to an OptionParser instance
|
36
98
|
# This adds an option like --fieldContext.fieldName="VALUE"
|
37
99
|
# @param opts [OptionParser]
|
@@ -65,6 +127,12 @@ module Morpheus
|
|
65
127
|
end
|
66
128
|
|
67
129
|
description = "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{option_type['defaultValue'] ? ' Default: '+option_type['defaultValue'].to_s : ''}"
|
130
|
+
if option_type['description']
|
131
|
+
description << "\n #{option_type['description']}"
|
132
|
+
end
|
133
|
+
if option_type['helpBlock']
|
134
|
+
description << "\n #{option_type['helpBlock']}"
|
135
|
+
end
|
68
136
|
# description = option_type['description'].to_s
|
69
137
|
# if option_type['defaultValue']
|
70
138
|
# description = "#{description} Default: #{option_type['defaultValue']}"
|
@@ -99,7 +167,7 @@ module Morpheus
|
|
99
167
|
# @return opts
|
100
168
|
def build_common_options(opts, options, includes=[])
|
101
169
|
#opts.separator ""
|
102
|
-
opts.separator "Common options:"
|
170
|
+
# opts.separator "Common options:"
|
103
171
|
includes = includes.clone
|
104
172
|
while (option_key = includes.shift) do
|
105
173
|
case option_key.to_sym
|
@@ -148,7 +216,7 @@ module Morpheus
|
|
148
216
|
end
|
149
217
|
|
150
218
|
opts.on( '-o', '--offset OFFSET', "Offset Results" ) do |offset|
|
151
|
-
options[:offset] = offset.to_i
|
219
|
+
options[:offset] = offset.to_i.abs
|
152
220
|
end
|
153
221
|
|
154
222
|
opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
|
@@ -163,6 +231,16 @@ module Morpheus
|
|
163
231
|
options[:direction] = "desc"
|
164
232
|
end
|
165
233
|
|
234
|
+
when :last_updated
|
235
|
+
# opts.on("--last-updated TIME", Time, "Filter by gte last updated") do |time|
|
236
|
+
opts.on("--last-updated TIME", String, "Filter by Last Updated (gte)") do |time|
|
237
|
+
begin
|
238
|
+
options[:lastUpdated] = parse_time(time)
|
239
|
+
rescue => e
|
240
|
+
raise OptionParser::InvalidArgument.new "Failed to parse time '#{time}'. Error: #{e}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
166
244
|
when :remote
|
167
245
|
|
168
246
|
# this is the only option now...
|
@@ -172,10 +250,15 @@ module Morpheus
|
|
172
250
|
end
|
173
251
|
|
174
252
|
# todo: also require this for talking to plain old HTTP
|
175
|
-
opts.on('-I','--insecure', "Allow
|
253
|
+
opts.on('-I','--insecure', "Allow insecure HTTPS communication. i.e. bad SSL certificate.") do |val|
|
254
|
+
options[:insecure] = true
|
176
255
|
Morpheus::RestClient.enable_ssl_verification = false
|
177
256
|
end
|
178
257
|
|
258
|
+
opts.on( '-T', '--token ACCESS_TOKEN', "Access Token for api requests. While authenticated to a remote, the current saved credentials are used." ) do |remote|
|
259
|
+
options[:remote_token] = remote
|
260
|
+
end
|
261
|
+
|
179
262
|
# skipping the rest of this for now..
|
180
263
|
|
181
264
|
next
|
@@ -204,10 +287,65 @@ module Morpheus
|
|
204
287
|
opts.on( '-y', '--yes', "Auto Confirm" ) do
|
205
288
|
options[:yes] = true
|
206
289
|
end
|
207
|
-
|
290
|
+
|
208
291
|
when :json
|
209
292
|
opts.on('-j','--json', "JSON Output") do
|
210
293
|
options[:json] = true
|
294
|
+
options[:format] = :json
|
295
|
+
end
|
296
|
+
|
297
|
+
opts.on('--json-raw', String, "JSON Output that is not so pretty.") do |val|
|
298
|
+
options[:json] = true
|
299
|
+
options[:format] = :json
|
300
|
+
options[:pretty_json] = false
|
301
|
+
end
|
302
|
+
|
303
|
+
when :yaml
|
304
|
+
opts.on(nil, '--yaml', "YAML Output") do
|
305
|
+
options[:yaml] = true
|
306
|
+
options[:format] = :yaml
|
307
|
+
end
|
308
|
+
|
309
|
+
when :csv
|
310
|
+
opts.on(nil, '--csv', "CSV Output") do
|
311
|
+
options[:csv] = true
|
312
|
+
options[:format] = :csv
|
313
|
+
#options[:csv_delim] = options[:csv_delim] || ","
|
314
|
+
end
|
315
|
+
|
316
|
+
opts.on('--csv-delim CHAR', String, "Delimiter for CSV Output values. Default: ','") do |val|
|
317
|
+
options[:csv] = true
|
318
|
+
options[:format] = :csv
|
319
|
+
val = val.gsub("\\n", "\n").gsub("\\r", "\r").gsub("\\t", "\t") if val.include?("\\")
|
320
|
+
options[:csv_delim] = val
|
321
|
+
end
|
322
|
+
|
323
|
+
opts.on('--csv-newline [CHAR]', String, "Delimiter for CSV Output rows. Default: '\\n'") do |val|
|
324
|
+
options[:csv] = true
|
325
|
+
options[:format] = :csv
|
326
|
+
if val == "no" || val == "none"
|
327
|
+
options[:csv_newline] = ""
|
328
|
+
else
|
329
|
+
val = val.gsub("\\n", "\n").gsub("\\r", "\r").gsub("\\t", "\t") if val.include?("\\")
|
330
|
+
options[:csv_newline] = val
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
opts.on(nil, '--csv-quotes', "Quote values for CSV Output. Default: false") do
|
335
|
+
options[:csv] = true
|
336
|
+
options[:format] = :csv
|
337
|
+
options[:csv_quotes] = true
|
338
|
+
end
|
339
|
+
|
340
|
+
opts.on(nil, '--csv-no-header', "Exclude header for CSV Output.") do
|
341
|
+
options[:csv] = true
|
342
|
+
options[:format] = :csv
|
343
|
+
options[:csv_no_header] = true
|
344
|
+
end
|
345
|
+
|
346
|
+
when :fields
|
347
|
+
opts.on('--fields x,y,z', Array, "Filter Output to a limited set of fields. Default is all fields.") do |val|
|
348
|
+
options[:include_fields] = val
|
211
349
|
end
|
212
350
|
|
213
351
|
when :dry_run
|
@@ -216,7 +354,7 @@ module Morpheus
|
|
216
354
|
end
|
217
355
|
|
218
356
|
when :quiet
|
219
|
-
opts.on('-q','--quiet', "No Output,
|
357
|
+
opts.on('-q','--quiet', "No Output, do not print to stdout") do
|
220
358
|
options[:quiet] = true
|
221
359
|
end
|
222
360
|
|
@@ -235,7 +373,7 @@ module Morpheus
|
|
235
373
|
opts.on('-V','--debug', "Print extra output for debugging. ") do
|
236
374
|
options[:debug] = true
|
237
375
|
Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
|
238
|
-
::RestClient.log = Morpheus::Logging.debug? ?
|
376
|
+
::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
|
239
377
|
# perhaps...
|
240
378
|
# create a new logger instance just for this command instance
|
241
379
|
# this way we don't elevate the global level for subsequent commands in a shell
|
@@ -276,6 +414,10 @@ module Morpheus
|
|
276
414
|
end
|
277
415
|
end
|
278
416
|
|
417
|
+
def my_help_command
|
418
|
+
"morpheus #{command_name} --help"
|
419
|
+
end
|
420
|
+
|
279
421
|
def subcommand_usage(*extra)
|
280
422
|
calling_method = caller[0][/`([^']*)'/, 1].to_s.sub('block in ', '')
|
281
423
|
subcommand_name = subcommands.key(calling_method)
|
@@ -287,14 +429,22 @@ module Morpheus
|
|
287
429
|
"Usage: morpheus #{command_name} #{subcommand_name} #{extra.join(' ')}".squeeze(' ').strip
|
288
430
|
end
|
289
431
|
|
290
|
-
|
291
|
-
|
432
|
+
# a string to describe the usage of your command
|
433
|
+
# this is what the --help option
|
434
|
+
# feel free to override this in your commands
|
435
|
+
def full_command_usage
|
436
|
+
out = ""
|
437
|
+
out << usage.to_s.strip if usage
|
438
|
+
out << "\n"
|
292
439
|
if !subcommands.empty?
|
293
|
-
|
440
|
+
out << "Commands:"
|
441
|
+
out << "\n"
|
294
442
|
subcommands.sort.each {|cmd, method|
|
295
|
-
|
443
|
+
out << "\t#{cmd.to_s}\n"
|
296
444
|
}
|
297
445
|
end
|
446
|
+
# out << "\n"
|
447
|
+
out
|
298
448
|
end
|
299
449
|
|
300
450
|
# a default handler
|
@@ -309,20 +459,24 @@ module Morpheus
|
|
309
459
|
# return self.send(default_subcommand, args || [])
|
310
460
|
# end
|
311
461
|
subcommand_name = args[0]
|
462
|
+
if args.empty?
|
463
|
+
print_error Morpheus::Terminal.angry_prompt
|
464
|
+
puts_error "[command] argument is required"
|
465
|
+
puts full_command_usage
|
466
|
+
exit 127
|
467
|
+
end
|
312
468
|
if args[0] == "-h" || args[0] == "--help" || args[0] == "help"
|
313
|
-
|
314
|
-
|
469
|
+
puts full_command_usage
|
470
|
+
return 0
|
315
471
|
end
|
316
472
|
if subcommand_aliases[subcommand_name]
|
317
473
|
subcommand_name = subcommand_aliases[subcommand_name]
|
318
474
|
end
|
319
475
|
cmd_method = subcommands[subcommand_name]
|
320
|
-
if subcommand_name && !cmd_method
|
321
|
-
puts "unknown command '#{self.command_name} #{subcommand_name}'"
|
322
|
-
end
|
323
476
|
if !cmd_method
|
324
|
-
|
325
|
-
|
477
|
+
print_error Morpheus::Terminal.angry_prompt
|
478
|
+
puts_error "'#{subcommand_name}' is not a morpheus #{self.command_name} command. See '#{my_help_command}'"
|
479
|
+
return 127
|
326
480
|
end
|
327
481
|
self.send(cmd_method, args[1..-1])
|
328
482
|
end
|
@@ -331,50 +485,73 @@ module Morpheus
|
|
331
485
|
raise "#{self} has not defined handle()!"
|
332
486
|
end
|
333
487
|
|
488
|
+
# executes block with each argument in the list
|
489
|
+
# @return [0|1] 0 if they were all successful, else 1
|
490
|
+
def run_command_for_each_arg(args, &block)
|
491
|
+
cmd_results = []
|
492
|
+
args.each do |arg|
|
493
|
+
begin
|
494
|
+
cur_result = yield arg
|
495
|
+
rescue SystemExit => err
|
496
|
+
cur_result = err.success? ? 0 : 1
|
497
|
+
end
|
498
|
+
cmd_results << cur_result
|
499
|
+
end
|
500
|
+
failed_cmd = cmd_results.find {|cmd_result| cmd_result == false || (cmd_result.is_a?(Integer) && cmd_result != 0) }
|
501
|
+
return failed_cmd ? failed_cmd : 0
|
502
|
+
end
|
503
|
+
|
334
504
|
# This supports the simple remote option eg. `instances add --remote "qa"`
|
335
505
|
# It will establish a connection to the pre-configured appliance named "qa"
|
336
506
|
# The calling command can populate @appliances and/or @appliance_name
|
337
507
|
# Otherwise, the current active appliance is used...
|
338
508
|
# This returns a new instance of Morpheus::APIClient (and sets @access_token, and @appliance)
|
339
509
|
# Your command should be ready to make api requests after this.
|
340
|
-
# todo: probably don't exit here, just return nil or raise
|
341
510
|
def establish_remote_appliance_connection(options)
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
end
|
511
|
+
# todo: probably refactor and don't rely on this method to set these instance vars
|
512
|
+
@appliance_name, @appliance_url, @access_token = nil, nil, nil
|
513
|
+
@api_client = nil
|
346
514
|
|
347
|
-
|
348
|
-
# it's probably better not to do that tho, just so it stays out of history files
|
349
|
-
|
350
|
-
# use a specific remote appliance by name
|
515
|
+
appliance = nil # @appliance..why not? laff
|
351
516
|
if options[:remote]
|
352
|
-
|
353
|
-
if
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
print_red_alert "You have no appliance named '#{@appliance_name}' configured. See the `remote add` command."
|
360
|
-
exit 1
|
361
|
-
end
|
362
|
-
@appliance = found_appliance
|
363
|
-
@appliance_name = @appliance_name
|
364
|
-
@appliance_url = @appliance[:host]
|
365
|
-
if options[:debug]
|
366
|
-
print dark,"# => Using remote appliance [#{@appliance_name}] #{@appliance_url}",reset,"\n" if !options[:quiet]
|
517
|
+
appliance = ::Morpheus::Cli::Remote.load_remote(options[:remote])
|
518
|
+
if !appliance
|
519
|
+
if ::Morpheus::Cli::Remote.appliances.empty?
|
520
|
+
raise_command_error "You have no appliances configured. See the `remote add` command."
|
521
|
+
else
|
522
|
+
raise_command_error "Remote appliance not found by the name '#{appliance_name}'"
|
523
|
+
end
|
367
524
|
end
|
368
525
|
else
|
369
|
-
|
526
|
+
appliance = ::Morpheus::Cli::Remote.load_active_remote()
|
527
|
+
if !appliance
|
528
|
+
if ::Morpheus::Cli::Remote.appliances.empty?
|
529
|
+
raise_command_error "You have no appliances configured. See the `remote add` command."
|
530
|
+
else
|
531
|
+
raise_command_error "No current appliance, see `remote use`."
|
532
|
+
end
|
533
|
+
end
|
370
534
|
end
|
535
|
+
@appliance_name = appliance[:name]
|
536
|
+
@appliance_url = appliance[:host] || appliance[:url] # it's :host in the YAML..heh
|
371
537
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
end
|
538
|
+
# todo: support old way of accepting --username and --password on the command line
|
539
|
+
# it's probably better not to do that tho, just so it stays out of history files
|
540
|
+
|
376
541
|
|
377
|
-
|
542
|
+
# if !@appliance_name && !@appliance_url
|
543
|
+
# raise_command_error "Please specify a remote appliance with -r or see the command `remote use`"
|
544
|
+
# end
|
545
|
+
|
546
|
+
Morpheus::Logging::DarkPrinter.puts "establishing connection to [#{@appliance_name}] #{@appliance_url}" if options[:debug]
|
547
|
+
#puts "#{dark} #=> establishing connection to [#{@appliance_name}] #{@appliance_url}#{reset}\n" if options[:debug]
|
548
|
+
|
549
|
+
|
550
|
+
# punt.. and just allow passing an access token instead for now..
|
551
|
+
# this skips saving to the appliances file and all that..
|
552
|
+
if options[:token]
|
553
|
+
@access_token = options[:token]
|
554
|
+
end
|
378
555
|
|
379
556
|
# ok, get some credentials.
|
380
557
|
# this prompts for username, password without options[:no_prompt]
|
@@ -400,8 +577,7 @@ module Morpheus
|
|
400
577
|
|
401
578
|
def verify_access_token!
|
402
579
|
if @access_token.empty?
|
403
|
-
|
404
|
-
exit 1
|
580
|
+
raise_command_error "Unable to acquire access token. Please verify your credentials and try again."
|
405
581
|
end
|
406
582
|
true
|
407
583
|
end
|
@@ -1,13 +1,60 @@
|
|
1
1
|
require 'term/ansicolor'
|
2
|
+
require 'morpheus/logging'
|
2
3
|
module Morpheus
|
3
4
|
module Cli
|
4
5
|
class CliRegistry
|
5
6
|
|
7
|
+
class BadAlias < StandardError
|
8
|
+
end
|
9
|
+
|
6
10
|
def initialize
|
7
11
|
@commands = {} # this is command => Class that includes ::CliCommand
|
8
12
|
@aliases = {} # this is alias => String full input string
|
9
13
|
end
|
10
14
|
|
15
|
+
def flush
|
16
|
+
@commands = {}
|
17
|
+
@aliases = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def all
|
21
|
+
@commands.reject {|cmd, klass| klass.hidden_command }
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(cmd_name)
|
25
|
+
@commands[cmd_name.to_sym]
|
26
|
+
end
|
27
|
+
|
28
|
+
def add(cmd_name, klass)
|
29
|
+
@commands[cmd_name.to_sym] = klass
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove(cmd_name)
|
33
|
+
@commands.delete(cmd_name.to_sym)
|
34
|
+
end
|
35
|
+
|
36
|
+
def all_aliases
|
37
|
+
@aliases
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_alias(alias_name)
|
41
|
+
@aliases[alias_name.to_sym]
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_alias(alias_name, command_string)
|
45
|
+
#return @commands[alias_name.to_sym]
|
46
|
+
if self.class.has_command?(alias_name)
|
47
|
+
raise BadAlias.new "alias name '#{alias_name}' is invalid. That is the name of a morpheus command."
|
48
|
+
elsif alias_name.to_s.downcase.strip == command_string.to_s.downcase.strip
|
49
|
+
raise BadAlias.new "alias #{alias_name}=#{command_string} is invalid..."
|
50
|
+
end
|
51
|
+
@aliases[alias_name.to_sym] = command_string
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove_alias(alias_name)
|
55
|
+
@aliases.delete(alias_name.to_sym)
|
56
|
+
end
|
57
|
+
|
11
58
|
class << self
|
12
59
|
include Term::ANSIColor
|
13
60
|
|
@@ -39,7 +86,7 @@ module Morpheus
|
|
39
86
|
# support aliases of multiple commands, semicolon delimiter
|
40
87
|
# todo:
|
41
88
|
all_commands = found_alias_command.gsub(ALIAS_SPLIT_REGEX, '__ALIAS_SPLIT_REGEX__').split('__ALIAS_SPLIT_REGEX__').collect {|it| it.to_s.strip }.select {|it| !it.empty? }.compact
|
42
|
-
|
89
|
+
Morpheus::Logging::DarkPrinter.puts "executing alias #{alias_name} as #{all_commands.join('; ')}" if Morpheus::Logging.debug?
|
43
90
|
all_commands.each do |a_command_string|
|
44
91
|
alias_args = a_command_string.to_s.split(/\s+/) # or just ' '
|
45
92
|
command_name = alias_args.shift
|
@@ -119,45 +166,6 @@ module Morpheus
|
|
119
166
|
return alias_name, command_string
|
120
167
|
end
|
121
168
|
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
def all
|
126
|
-
@commands.reject {|cmd, klass| klass.hidden_command }
|
127
|
-
end
|
128
|
-
|
129
|
-
def get(cmd_name)
|
130
|
-
@commands[cmd_name.to_sym]
|
131
|
-
end
|
132
|
-
|
133
|
-
def add(cmd_name, klass)
|
134
|
-
@commands[cmd_name.to_sym] = klass
|
135
|
-
end
|
136
|
-
|
137
|
-
def remove(cmd_name)
|
138
|
-
@commands.delete(cmd_name.to_sym)
|
139
|
-
end
|
140
|
-
|
141
|
-
def all_aliases
|
142
|
-
@aliases
|
143
|
-
end
|
144
|
-
|
145
|
-
def get_alias(alias_name)
|
146
|
-
@aliases[alias_name.to_sym]
|
147
|
-
end
|
148
|
-
|
149
|
-
def add_alias(alias_name, command_string)
|
150
|
-
#return @commands[alias_name.to_sym]
|
151
|
-
if self.class.has_command?(alias_name)
|
152
|
-
raise "alias name '#{alias_name}' is invalid. That is the name of a morpheus command."
|
153
|
-
elsif alias_name.to_s.downcase.strip == command_string.to_s.downcase.strip
|
154
|
-
raise "alias #{alias_name}=#{command_string} is invalid..."
|
155
|
-
end
|
156
|
-
@aliases[alias_name.to_sym] = command_string
|
157
|
-
end
|
158
|
-
|
159
|
-
def remove_alias(alias_name)
|
160
|
-
@aliases.delete(alias_name.to_sym)
|
161
169
|
end
|
162
170
|
|
163
171
|
end
|