morpheus-cli 2.10.3 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|