morpheus-cli 3.1.2.1 → 3.2.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/lib/morpheus/api/api_client.rb +6 -2
- data/lib/morpheus/api/license_interface.rb +7 -0
- data/lib/morpheus/api/monitoring_apps_interface.rb +15 -2
- data/lib/morpheus/api/{checks_interface.rb → monitoring_checks_interface.rb} +8 -21
- data/lib/morpheus/api/monitoring_groups_interface.rb +23 -2
- data/lib/morpheus/api/{incidents_interface.rb → monitoring_incidents_interface.rb} +5 -5
- data/lib/morpheus/api/monitoring_interface.rb +4 -4
- data/lib/morpheus/api/user_groups_interface.rb +65 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/curl_command.rb +9 -7
- data/lib/morpheus/cli/dot_file.rb +11 -5
- data/lib/morpheus/cli/echo_command.rb +27 -3
- data/lib/morpheus/cli/license.rb +109 -20
- data/lib/morpheus/cli/login.rb +2 -0
- data/lib/morpheus/cli/logout.rb +2 -0
- data/lib/morpheus/cli/mixins/monitoring_helper.rb +97 -37
- data/lib/morpheus/cli/mixins/print_helper.rb +5 -2
- data/lib/morpheus/cli/monitoring_apps_command.rb +564 -9
- data/lib/morpheus/cli/monitoring_checks_command.rb +326 -93
- data/lib/morpheus/cli/monitoring_contacts_command.rb +2 -2
- data/lib/morpheus/cli/monitoring_groups_command.rb +540 -10
- data/lib/morpheus/cli/monitoring_incidents_command.rb +88 -56
- data/lib/morpheus/cli/remote.rb +6 -0
- data/lib/morpheus/cli/roles.rb +1 -1
- data/lib/morpheus/cli/set_prompt_command.rb +1 -0
- data/lib/morpheus/cli/shell.rb +17 -8
- data/lib/morpheus/cli/user_groups_command.rb +574 -0
- data/lib/morpheus/cli/users.rb +221 -115
- data/lib/morpheus/cli/version.rb +1 -1
- data/morpheus-cli.gemspec +1 -2
- metadata +11 -8
@@ -5,14 +5,9 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
5
5
|
include Morpheus::Cli::CliCommand
|
6
6
|
include Morpheus::Cli::MonitoringHelper
|
7
7
|
|
8
|
-
set_command_name :
|
9
|
-
register_subcommands :list, :stats, :get, :history, :notifications, :update, :close, :reopen, :
|
10
|
-
set_default_subcommand :list
|
8
|
+
set_command_name :'monitor-incidents'
|
9
|
+
register_subcommands :list, :stats, :get, :history, :notifications, :update, :close, :reopen, :mute, :unmute
|
11
10
|
|
12
|
-
def initialize()
|
13
|
-
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
14
|
-
end
|
15
|
-
|
16
11
|
def connect(opts)
|
17
12
|
@api_client = establish_remote_appliance_connection(opts)
|
18
13
|
@monitoring_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).monitoring
|
@@ -33,7 +28,7 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
33
28
|
opts.on('--severity LIST', Array, "Filter by severity. critical, warning, info") do |list|
|
34
29
|
params['severity'] = list
|
35
30
|
end
|
36
|
-
build_common_options(opts, options, [:list, :last_updated, :json, :csv, :fields, :
|
31
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
37
32
|
end
|
38
33
|
optparse.parse!(args)
|
39
34
|
connect(options)
|
@@ -41,27 +36,26 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
41
36
|
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
42
37
|
params[k] = options[k] unless options[k].nil?
|
43
38
|
end
|
44
|
-
# JD: lastUpdated 500ing, incidents don't have that property ? =o Fix it!
|
45
|
-
|
46
39
|
if options[:dry_run]
|
47
40
|
print_dry_run @monitoring_interface.incidents.dry.list(params)
|
48
41
|
return
|
49
42
|
end
|
50
|
-
|
51
43
|
json_response = @monitoring_interface.incidents.list(params)
|
44
|
+
if options[:include_fields]
|
45
|
+
json_response = {"incidents" => filter_data(json_response["incidents"], options[:include_fields]) }
|
46
|
+
end
|
52
47
|
if options[:json]
|
53
|
-
if options[:include_fields]
|
54
|
-
json_response = {"incidents" => filter_data(json_response["incidents"], options[:include_fields]) }
|
55
|
-
end
|
56
48
|
puts as_json(json_response, options)
|
57
49
|
return 0
|
58
|
-
|
59
|
-
|
50
|
+
elsif options[:yaml]
|
51
|
+
puts as_yaml(json_response, options)
|
52
|
+
return 0
|
53
|
+
elsif options[:csv]
|
60
54
|
puts records_as_csv(json_response['incidents'], options)
|
61
55
|
return 0
|
62
56
|
end
|
63
57
|
incidents = json_response['incidents']
|
64
|
-
title = "Morpheus Incidents"
|
58
|
+
title = "Morpheus Monitoring Incidents"
|
65
59
|
subtitles = []
|
66
60
|
# if group
|
67
61
|
# subtitles << "Group: #{group['name']}".strip
|
@@ -104,7 +98,7 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
104
98
|
opts.on( '-o', '--offset OFFSET', "Offset open incidents results for pagination." ) do |offset|
|
105
99
|
options[:offset] = offset.to_i.abs
|
106
100
|
end
|
107
|
-
build_common_options(opts, options, [:json, :fields, :
|
101
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
108
102
|
end
|
109
103
|
optparse.parse!(args)
|
110
104
|
connect(options)
|
@@ -186,7 +180,7 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
186
180
|
opts.on(nil,'--notifications', "Display Incident Notifications") do |val|
|
187
181
|
options[:show_notifications] = true
|
188
182
|
end
|
189
|
-
build_common_options(opts, options, [:json, :csv, :fields, :dry_run, :remote])
|
183
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
190
184
|
end
|
191
185
|
optparse.parse!(args)
|
192
186
|
if args.count < 1
|
@@ -211,14 +205,17 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
211
205
|
json_response = @monitoring_interface.incidents.get(incident['id'])
|
212
206
|
incident = json_response['incident']
|
213
207
|
|
208
|
+
if options[:include_fields]
|
209
|
+
json_response = {"incident" => filter_data(json_response["incident"], options[:include_fields]) }
|
210
|
+
end
|
214
211
|
if options[:json]
|
215
|
-
if options[:include_fields]
|
216
|
-
json_response = {"incident" => filter_data(json_response["incident"], options[:include_fields]) }
|
217
|
-
end
|
218
212
|
puts as_json(json_response, options)
|
219
213
|
return 0
|
214
|
+
elsif options[:yaml]
|
215
|
+
puts as_yaml(json_response, options)
|
216
|
+
return 0
|
220
217
|
elsif options[:csv]
|
221
|
-
puts records_as_csv(
|
218
|
+
puts records_as_csv(json_response['incident'], options)
|
222
219
|
return 0
|
223
220
|
end
|
224
221
|
|
@@ -232,6 +229,7 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
232
229
|
"End" => lambda {|it| format_local_dt(it['endDate']) },
|
233
230
|
"Duration" => lambda {|it| format_duration(it['startDate'], it['endDate']) },
|
234
231
|
"Status" => lambda {|it| format_monitoring_issue_status(it) },
|
232
|
+
"Muted" => lambda {|it| it['inUptime'] ? 'No' : 'Yes' },
|
235
233
|
"Visibility" => 'visibility',
|
236
234
|
"Last Check" => lambda {|it| format_local_dt(it['lastCheckTime']) },
|
237
235
|
"Last Error" => lambda {|it| it['lastError'] },
|
@@ -302,13 +300,10 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
302
300
|
params = {}
|
303
301
|
optparse = OptionParser.new do|opts|
|
304
302
|
opts.banner = subcommand_usage("[id] [options]")
|
305
|
-
# opts.on('--status LIST', Array, "Filter by status. open, closed") do |list|
|
306
|
-
# params['status'] = list
|
307
|
-
# end
|
308
303
|
opts.on('--severity LIST', Array, "Filter by severity. critical, warning, info") do |list|
|
309
304
|
params['severity'] = list
|
310
305
|
end
|
311
|
-
build_common_options(opts, options, [:list, :last_updated, :json, :csv, :fields, :json, :dry_run])
|
306
|
+
build_common_options(opts, options, [:list, :last_updated, :json, :csv, :fields, :json, :dry_run, :remote])
|
312
307
|
end
|
313
308
|
optparse.parse!(args)
|
314
309
|
if args.count < 1
|
@@ -366,7 +361,7 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
366
361
|
options = {}
|
367
362
|
optparse = OptionParser.new do|opts|
|
368
363
|
opts.banner = subcommand_usage("[id] [options]")
|
369
|
-
build_common_options(opts, options, [:list, :json, :csv, :fields, :json, :dry_run])
|
364
|
+
build_common_options(opts, options, [:list, :json, :csv, :fields, :json, :dry_run, :remote])
|
370
365
|
end
|
371
366
|
optparse.parse!(args)
|
372
367
|
if args.count < 1
|
@@ -505,55 +500,92 @@ class Morpheus::Cli::MonitoringIncidentsCommand
|
|
505
500
|
end
|
506
501
|
|
507
502
|
|
508
|
-
def
|
503
|
+
def mute(args)
|
509
504
|
options = {}
|
510
505
|
params = {'enabled' => true}
|
511
|
-
optparse = OptionParser.new do|opts|
|
512
|
-
opts.banner = subcommand_usage("[id
|
513
|
-
|
514
|
-
# opts.on("--enabled BOOL", String, "Quarantine can be removed with --enabled false") do |val|
|
515
|
-
# params['enabled'] = ['on','true'].include?(val.to_s.downcase)
|
516
|
-
# end
|
517
|
-
opts.on("-d", "--disabled", "Disable Quarantine instead") do
|
506
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
507
|
+
opts.banner = subcommand_usage("[id]")
|
508
|
+
opts.on(nil, "--disable", "Disable mute state instead, the same as unmute") do
|
518
509
|
params['enabled'] = false
|
519
510
|
end
|
520
|
-
build_common_options(opts, options, [:json, :dry_run, :quiet])
|
511
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
512
|
+
opts.footer = "Mute an incident." + "\n" +
|
513
|
+
"[id] is required. This is the id of an incident."
|
521
514
|
end
|
522
515
|
optparse.parse!(args)
|
523
|
-
if args.count
|
516
|
+
if args.count != 1
|
524
517
|
puts optparse
|
525
|
-
|
518
|
+
return 1
|
526
519
|
end
|
527
520
|
connect(options)
|
528
|
-
|
529
521
|
begin
|
530
522
|
incident = find_incident_by_id(args[0])
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
523
|
+
# construct payload
|
524
|
+
payload = nil
|
525
|
+
if options[:payload]
|
526
|
+
payload = options[:payload]
|
527
|
+
else
|
528
|
+
payload = params
|
529
|
+
end
|
530
|
+
if options[:dry_run]
|
531
|
+
print_dry_run @monitoring_interface.incidents.dry.quarantine(incident["id"], payload)
|
532
|
+
return 0
|
533
|
+
end
|
534
|
+
json_response = @monitoring_interface.incidents.quarantine(incident["id"], payload)
|
535
|
+
if options[:json]
|
536
|
+
puts as_json(json_response, options)
|
537
|
+
elsif !options[:quiet]
|
538
|
+
if params['enabled']
|
539
|
+
print_green_success "Muted incident #{incident['id']}"
|
540
|
+
else
|
541
|
+
print_green_success "Unmuted incident #{incident['id']}"
|
542
|
+
end
|
543
|
+
_get(incident['id'], {})
|
536
544
|
end
|
545
|
+
return 0
|
546
|
+
rescue RestClient::Exception => e
|
547
|
+
print_rest_exception(e, options)
|
548
|
+
exit 1
|
549
|
+
end
|
550
|
+
end
|
537
551
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
552
|
+
def unmute(args)
|
553
|
+
options = {}
|
554
|
+
params = {'enabled' => false}
|
555
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
556
|
+
opts.banner = subcommand_usage("[id]")
|
557
|
+
build_common_options(opts, options, [:payload, :json, :dry_run, :quiet, :remote])
|
558
|
+
opts.footer = "Unmute an incident." + "\n" +
|
559
|
+
"[id] is required. This is the id of an incident."
|
560
|
+
end
|
561
|
+
optparse.parse!(args)
|
562
|
+
if args.count != 1
|
563
|
+
puts optparse
|
564
|
+
return 1
|
565
|
+
end
|
566
|
+
connect(options)
|
543
567
|
|
568
|
+
begin
|
569
|
+
incident = find_incident_by_id(args[0])
|
570
|
+
# construct payload
|
571
|
+
payload = nil
|
572
|
+
if options[:payload]
|
573
|
+
payload = options[:payload]
|
574
|
+
else
|
575
|
+
payload = params
|
576
|
+
end
|
544
577
|
if options[:dry_run]
|
545
|
-
print_dry_run @monitoring_interface.incidents.dry.
|
546
|
-
return
|
578
|
+
print_dry_run @monitoring_interface.incidents.dry.quarantine(incident["id"], payload)
|
579
|
+
return 0
|
547
580
|
end
|
548
|
-
|
549
|
-
json_response = @monitoring_interface.incidents.update(incident["id"], payload)
|
581
|
+
json_response = @monitoring_interface.incidents.quarantine(incident["id"], payload)
|
550
582
|
if options[:json]
|
551
583
|
puts as_json(json_response, options)
|
552
584
|
elsif !options[:quiet]
|
553
|
-
print_green_success "
|
585
|
+
print_green_success "Unmuted incident #{incident['id']}"
|
554
586
|
_get(incident['id'], {})
|
555
587
|
end
|
556
|
-
|
588
|
+
return 0
|
557
589
|
rescue RestClient::Exception => e
|
558
590
|
print_rest_exception(e, options)
|
559
591
|
exit 1
|
data/lib/morpheus/cli/remote.rb
CHANGED
@@ -555,6 +555,8 @@ EOT
|
|
555
555
|
end
|
556
556
|
print_green_success "Deleted remote #{appliance_name}"
|
557
557
|
list([])
|
558
|
+
# recalcuate echo vars
|
559
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
558
560
|
# recalculate shell prompt after this change
|
559
561
|
if Morpheus::Cli::Shell.instance
|
560
562
|
Morpheus::Cli::Shell.instance.reinitialize()
|
@@ -595,6 +597,8 @@ EOT
|
|
595
597
|
appliance[:active] = true
|
596
598
|
appliance = ::Morpheus::Cli::Remote.save_remote(appliance_name, appliance)
|
597
599
|
|
600
|
+
# recalcuate echo vars
|
601
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
598
602
|
# recalculate shell prompt after this change
|
599
603
|
if Morpheus::Cli::Shell.instance
|
600
604
|
Morpheus::Cli::Shell.instance.reinitialize()
|
@@ -623,6 +627,8 @@ EOT
|
|
623
627
|
end
|
624
628
|
Morpheus::Cli::Remote.clear_active_appliance()
|
625
629
|
puts "You are no longer using the appliance #{@appliance_name}"
|
630
|
+
# recalcuate echo vars
|
631
|
+
Morpheus::Cli::Echo.recalculate_variable_map()
|
626
632
|
# recalculate shell prompt after this change
|
627
633
|
if Morpheus::Cli::Shell.instance
|
628
634
|
Morpheus::Cli::Shell.instance.reinitialize()
|
data/lib/morpheus/cli/roles.rb
CHANGED
@@ -151,7 +151,7 @@ class Morpheus::Cli::Roles
|
|
151
151
|
print cyan
|
152
152
|
description_cols = {
|
153
153
|
"ID" => 'id',
|
154
|
-
"Name" => '
|
154
|
+
"Name" => 'authority',
|
155
155
|
"Description" => 'description',
|
156
156
|
"Scope" => lambda {|it| it['scope'] },
|
157
157
|
"Type" => lambda {|it| format_role_type(it) },
|
data/lib/morpheus/cli/shell.rb
CHANGED
@@ -63,14 +63,15 @@ class Morpheus::Cli::Shell
|
|
63
63
|
#@prompt = Morpheus::Terminal.instance.prompt.to_s #.dup
|
64
64
|
@prompt = my_terminal.prompt
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
variable_map = Morpheus::Cli::Echo.variable_map
|
67
|
+
# variable_map = {
|
68
|
+
# '%cyan' => cyan, '%magenta' => magenta, '%red' => red, '%mgreen' => green, '%yellow' => yellow, '%dark' => dark, '%reset' => reset,
|
69
|
+
# '%remote' => @appliance_name.to_s, '%remote_url' => @appliance_url.to_s,
|
70
|
+
# '%username' => @current_username.to_s
|
71
|
+
# }
|
71
72
|
@calculated_prompt = @prompt.to_s.dup
|
72
|
-
|
73
|
-
@calculated_prompt.gsub!(
|
73
|
+
variable_map.each do |k, v|
|
74
|
+
@calculated_prompt.gsub!(k.to_s, v.to_s)
|
74
75
|
end
|
75
76
|
# cleanup empty brackets caused by var value
|
76
77
|
@calculated_prompt = @calculated_prompt.gsub("[]", "").gsub("<>", "").gsub("{}", "")
|
@@ -237,11 +238,19 @@ class Morpheus::Cli::Shell
|
|
237
238
|
n_commands = input.sub(/^history\s?/, '').sub(/\-n\s?/, '')
|
238
239
|
n_commands = n_commands.empty? ? 25 : n_commands.to_i
|
239
240
|
cmd_numbers = @history.keys.last(n_commands)
|
240
|
-
|
241
|
+
if cmd_numbers.size == 1
|
242
|
+
puts "Last command"
|
243
|
+
else
|
244
|
+
puts "Last #{cmd_numbers.size} commands"
|
245
|
+
end
|
241
246
|
cmd_numbers.each do |cmd_number|
|
242
247
|
cmd = @history[cmd_number]
|
243
248
|
puts "#{cmd_number.to_s.rjust(3, ' ')} #{cmd}"
|
244
249
|
end
|
250
|
+
last_cmd = cmd_numbers.last ? @history[cmd_numbers.last] : nil
|
251
|
+
if input != last_cmd # no consecutive
|
252
|
+
log_history_command(input)
|
253
|
+
end
|
245
254
|
return 0
|
246
255
|
elsif input == 'clear'
|
247
256
|
print "\e[H\e[2J"
|
@@ -0,0 +1,574 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
require 'morpheus/cli/mixins/accounts_helper'
|
3
|
+
|
4
|
+
class Morpheus::Cli::UserGroupsCommand
|
5
|
+
include Morpheus::Cli::CliCommand
|
6
|
+
include Morpheus::Cli::AccountsHelper
|
7
|
+
|
8
|
+
set_command_name :'user-groups'
|
9
|
+
register_subcommands :list, :get, :add, :update, :remove
|
10
|
+
register_subcommands :'add-user' => :add_user
|
11
|
+
register_subcommands :'remove-user' => :remove_user
|
12
|
+
|
13
|
+
def connect(opts)
|
14
|
+
@api_client = establish_remote_appliance_connection(opts)
|
15
|
+
@user_groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).user_groups
|
16
|
+
@users_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).users
|
17
|
+
@accounts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).accounts
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle(args)
|
21
|
+
handle_subcommand(args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def list(args)
|
25
|
+
options = {}
|
26
|
+
params = {}
|
27
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
28
|
+
opts.banner = subcommand_usage()
|
29
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
30
|
+
end
|
31
|
+
optparse.parse!(args)
|
32
|
+
connect(options)
|
33
|
+
begin
|
34
|
+
[:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
|
35
|
+
params[k] = options[k] unless options[k].nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
if options[:dry_run]
|
39
|
+
print_dry_run @user_groups_interface.dry.list(nil, params)
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
json_response = @user_groups_interface.list(nil, params)
|
44
|
+
if options[:include_fields]
|
45
|
+
json_response = {"userGroups" => filter_data(json_response["userGroups"], options[:include_fields]) }
|
46
|
+
end
|
47
|
+
if options[:json]
|
48
|
+
puts as_json(json_response, options)
|
49
|
+
return 0
|
50
|
+
elsif options[:csv]
|
51
|
+
puts records_as_csv(json_response['userGroups'], options)
|
52
|
+
return 0
|
53
|
+
elsif options[:yaml]
|
54
|
+
puts as_yaml(json_response, options)
|
55
|
+
return 0
|
56
|
+
end
|
57
|
+
user_groups = json_response['userGroups']
|
58
|
+
title = "Morpheus User Groups"
|
59
|
+
subtitles = []
|
60
|
+
# if group
|
61
|
+
# subtitles << "Group: #{group['name']}".strip
|
62
|
+
# end
|
63
|
+
# if cloud
|
64
|
+
# subtitles << "Cloud: #{cloud['name']}".strip
|
65
|
+
# end
|
66
|
+
if params[:phrase]
|
67
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
68
|
+
end
|
69
|
+
print_h1 title, subtitles
|
70
|
+
if user_groups.empty?
|
71
|
+
print cyan,"No user groups found.",reset,"\n"
|
72
|
+
else
|
73
|
+
print_user_groups_table(user_groups, options)
|
74
|
+
print_results_pagination(json_response, {:label => "user group", :n_label => "user groups"})
|
75
|
+
# print_results_pagination(json_response)
|
76
|
+
end
|
77
|
+
print reset,"\n"
|
78
|
+
rescue RestClient::Exception => e
|
79
|
+
print_rest_exception(e, options)
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get(args)
|
85
|
+
options = {}
|
86
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
87
|
+
opts.banner = subcommand_usage("[name]")
|
88
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
89
|
+
end
|
90
|
+
optparse.parse!(args)
|
91
|
+
if args.count < 1
|
92
|
+
puts optparse
|
93
|
+
exit 1
|
94
|
+
end
|
95
|
+
connect(options)
|
96
|
+
id_list = parse_id_list(args)
|
97
|
+
return run_command_for_each_arg(id_list) do |arg|
|
98
|
+
_get(arg, options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _get(id, options)
|
103
|
+
|
104
|
+
begin
|
105
|
+
user_group = find_user_group_by_name_or_id(nil, id)
|
106
|
+
if user_group.nil?
|
107
|
+
return 1
|
108
|
+
end
|
109
|
+
if options[:dry_run]
|
110
|
+
print_dry_run @user_groups_interface.dry.get(nil, user_group['id'])
|
111
|
+
return
|
112
|
+
end
|
113
|
+
json_response = @user_groups_interface.get(nil, user_group['id'])
|
114
|
+
user_group = json_response['userGroup']
|
115
|
+
users = user_group['users'] || []
|
116
|
+
if options[:include_fields]
|
117
|
+
json_response = {"userGroup" => filter_data(json_response["userGroup"], options[:include_fields]) }
|
118
|
+
end
|
119
|
+
if options[:json]
|
120
|
+
puts as_json(json_response, options)
|
121
|
+
return 0
|
122
|
+
elsif options[:yaml]
|
123
|
+
puts as_yaml(json_response, options)
|
124
|
+
return 0
|
125
|
+
elsif options[:csv]
|
126
|
+
puts records_as_csv([json_response['userGroup']], options)
|
127
|
+
return 0
|
128
|
+
end
|
129
|
+
|
130
|
+
print_h1 "User Group Details"
|
131
|
+
print cyan
|
132
|
+
description_cols = {
|
133
|
+
"ID" => lambda {|it| it['id'] },
|
134
|
+
#"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
135
|
+
"Name" => lambda {|it| it['name'] },
|
136
|
+
"Description" => lambda {|it| it['description'] },
|
137
|
+
"Server Group" => lambda {|it| it['serverGroup'] },
|
138
|
+
"Sudo Access" => lambda {|it| format_boolean it['sudoAccess'] },
|
139
|
+
# "Shared User" => lambda {|it| format_boolean it['sharedUser'] },
|
140
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
141
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
142
|
+
}
|
143
|
+
print_description_list(description_cols, user_group)
|
144
|
+
|
145
|
+
## Users
|
146
|
+
if users.size == 1
|
147
|
+
print_h2 "User (1)"
|
148
|
+
else
|
149
|
+
print_h2 "Users (#{users.size})"
|
150
|
+
end
|
151
|
+
if users.size == 0
|
152
|
+
print yellow,"No users",reset,"\n"
|
153
|
+
else
|
154
|
+
user_columns = [
|
155
|
+
{"ID" => lambda {|user| user['id'] } },
|
156
|
+
{"USERNAME" => lambda {|user| user['username'] } },
|
157
|
+
{"NAME" => lambda {|user| user['displayName'] } },
|
158
|
+
]
|
159
|
+
print as_pretty_table(users, user_columns)
|
160
|
+
end
|
161
|
+
|
162
|
+
print reset,"\n"
|
163
|
+
|
164
|
+
rescue RestClient::Exception => e
|
165
|
+
print_rest_exception(e, options)
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def add(args)
|
171
|
+
options = {}
|
172
|
+
params = {}
|
173
|
+
user_ids = nil
|
174
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
175
|
+
opts.banner = subcommand_usage("[name]")
|
176
|
+
opts.on('--name VALUE', String, "Name") do |val|
|
177
|
+
params['name'] = val
|
178
|
+
end
|
179
|
+
opts.on('--description VALUE', String, "Description") do |val|
|
180
|
+
params['description'] = val
|
181
|
+
end
|
182
|
+
opts.on('--sudoUser [on|off]', String, "Sudo Access") do |val|
|
183
|
+
params['sudoUser'] = val.nil? || val.to_s == 'on' || val.to_s == 'true'
|
184
|
+
end
|
185
|
+
opts.on('--serverGroup VALUE', String, "Server Group") do |val|
|
186
|
+
params['name'] = val
|
187
|
+
end
|
188
|
+
opts.on('--users LIST', Array, "Users to include in this group, comma separated list of IDs or usernames") do |list|
|
189
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
190
|
+
user_ids = []
|
191
|
+
else
|
192
|
+
user_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
193
|
+
end
|
194
|
+
end
|
195
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
196
|
+
opts.footer = "Create a new user group." + "\n" +
|
197
|
+
"[name] is required and can be passed as --name instead."
|
198
|
+
end
|
199
|
+
optparse.parse!(args)
|
200
|
+
if args.count > 1
|
201
|
+
print_error Morpheus::Terminal.angry_prompt
|
202
|
+
puts_error "wrong number of arguments, expected 0-1 and got #{args.count}\n#{optparse}"
|
203
|
+
return 1
|
204
|
+
end
|
205
|
+
# support [name] as first argument
|
206
|
+
if args[0]
|
207
|
+
params['name'] = args[0]
|
208
|
+
end
|
209
|
+
connect(options)
|
210
|
+
begin
|
211
|
+
# construct payload
|
212
|
+
payload = nil
|
213
|
+
if options[:payload]
|
214
|
+
payload = options[:payload]
|
215
|
+
else
|
216
|
+
# merge -O options into normally parsed options
|
217
|
+
params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
218
|
+
users = []
|
219
|
+
if user_ids
|
220
|
+
user_ids.each do |user_id|
|
221
|
+
user = find_user_by_username_or_id(nil, user_id)
|
222
|
+
return 1 if user.nil?
|
223
|
+
users << user
|
224
|
+
end
|
225
|
+
params['users'] = users.collect {|it| it['id'] }
|
226
|
+
end
|
227
|
+
# todo: prompt?
|
228
|
+
payload = {'userGroup' => params}
|
229
|
+
end
|
230
|
+
if options[:dry_run]
|
231
|
+
print_dry_run @user_groups_interface.dry.create(nil, payload)
|
232
|
+
return
|
233
|
+
end
|
234
|
+
json_response = @user_groups_interface.create(nil, payload)
|
235
|
+
if options[:json]
|
236
|
+
puts as_json(json_response, options)
|
237
|
+
elsif !options[:quiet]
|
238
|
+
user_group = json_response['userGroup']
|
239
|
+
print_green_success "Added user group #{user_group['name']}"
|
240
|
+
_get(user_group['id'], {})
|
241
|
+
end
|
242
|
+
return 0
|
243
|
+
rescue RestClient::Exception => e
|
244
|
+
print_rest_exception(e, options)
|
245
|
+
exit 1
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
def update(args)
|
251
|
+
options = {}
|
252
|
+
params = {}
|
253
|
+
user_ids = nil
|
254
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
255
|
+
opts.banner = subcommand_usage("[name]")
|
256
|
+
opts.on('--name VALUE', String, "Name for this user group") do |val|
|
257
|
+
params['name'] = val
|
258
|
+
end
|
259
|
+
opts.on('--description VALUE', String, "Description") do |val|
|
260
|
+
params['description'] = val
|
261
|
+
end
|
262
|
+
opts.on('--sudoUser [on|off]', String, "Sudo Access. Default is off.") do |val|
|
263
|
+
params['sudoUser'] = val.nil? || val.to_s == 'on' || val.to_s == 'true'
|
264
|
+
end
|
265
|
+
opts.on('--users LIST', Array, "Users to include in this group, comma separated list of IDs or usernames") do |list|
|
266
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
267
|
+
user_ids = []
|
268
|
+
else
|
269
|
+
user_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
270
|
+
end
|
271
|
+
end
|
272
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
|
273
|
+
opts.footer = "Update a user group." + "\n" +
|
274
|
+
"[name] is required. This is the name or id of a user group."
|
275
|
+
end
|
276
|
+
optparse.parse!(args)
|
277
|
+
if args.count != 1
|
278
|
+
print_error Morpheus::Terminal.angry_prompt
|
279
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
280
|
+
return 1
|
281
|
+
end
|
282
|
+
connect(options)
|
283
|
+
begin
|
284
|
+
user_group = find_user_group_by_name_or_id(nil, args[0])
|
285
|
+
if user_group.nil?
|
286
|
+
return 1
|
287
|
+
end
|
288
|
+
# construct payload
|
289
|
+
payload = nil
|
290
|
+
if options[:payload]
|
291
|
+
payload = options[:payload]
|
292
|
+
else
|
293
|
+
# merge -O options into normally parsed options
|
294
|
+
params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
295
|
+
if user_ids
|
296
|
+
users = []
|
297
|
+
user_ids.each do |user_id|
|
298
|
+
user = find_user_by_username_or_id(nil, user_id)
|
299
|
+
return 1 if user.nil?
|
300
|
+
users << user
|
301
|
+
end
|
302
|
+
params['users'] = users.collect {|it| it['id'] }
|
303
|
+
else
|
304
|
+
# prevent server from clearing this!
|
305
|
+
params['users'] = user_group['users'] #.collect {|it| it['id'] }
|
306
|
+
end
|
307
|
+
# todo: prompt?
|
308
|
+
payload = {'userGroup' => params}
|
309
|
+
end
|
310
|
+
if options[:dry_run]
|
311
|
+
print_dry_run @user_groups_interface.dry.update(nil, user_group["id"], payload)
|
312
|
+
return
|
313
|
+
end
|
314
|
+
json_response = @user_groups_interface.update(nil, user_group["id"], payload)
|
315
|
+
if options[:json]
|
316
|
+
puts as_json(json_response, options)
|
317
|
+
elsif !options[:quiet]
|
318
|
+
print_green_success "Updated user group #{user_group['name']}"
|
319
|
+
_get(user_group['id'], {})
|
320
|
+
end
|
321
|
+
return 0
|
322
|
+
rescue RestClient::Exception => e
|
323
|
+
print_rest_exception(e, options)
|
324
|
+
exit 1
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def add_user(args)
|
329
|
+
options = {}
|
330
|
+
params = {}
|
331
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
332
|
+
opts.banner = subcommand_usage("[name] [user]")
|
333
|
+
build_common_options(opts, options, [:json, :dry_run, :remote, :quiet])
|
334
|
+
opts.footer = "Add a user to a user group.\n" +
|
335
|
+
"[name] is required. This is the name or id of a user group.\n" +
|
336
|
+
"[user] is required. This is the username or id of a user. More than one can be passed."
|
337
|
+
end
|
338
|
+
optparse.parse!(args)
|
339
|
+
if args.count < 2
|
340
|
+
puts optparse
|
341
|
+
return 1
|
342
|
+
end
|
343
|
+
connect(options)
|
344
|
+
begin
|
345
|
+
user_group = find_user_group_by_name_or_id(nil, args[0])
|
346
|
+
if user_group.nil?
|
347
|
+
return 1
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
# construct payload
|
352
|
+
payload = nil
|
353
|
+
if options[:payload]
|
354
|
+
payload = options[:payload]
|
355
|
+
else
|
356
|
+
user_ids = args[1..-1]
|
357
|
+
users = []
|
358
|
+
user_ids.each do |user_id|
|
359
|
+
user = find_user_by_username_or_id(nil, user_id)
|
360
|
+
return 1 if user.nil?
|
361
|
+
users << user
|
362
|
+
end
|
363
|
+
add_user_ids = users.collect {|it| it['id'] }
|
364
|
+
current_users = (user_group['users'] || [])
|
365
|
+
current_user_ids = current_users.collect {|it| it['id'] }
|
366
|
+
new_user_ids = (current_user_ids + add_user_ids).uniq
|
367
|
+
user_group_payload = {} # user_group
|
368
|
+
user_group_payload['users'] = new_user_ids
|
369
|
+
payload = {'userGroup' => user_group_payload}
|
370
|
+
end
|
371
|
+
if options[:dry_run]
|
372
|
+
print_dry_run @user_groups_interface.dry.update(nil, user_group["id"], payload)
|
373
|
+
return 0
|
374
|
+
end
|
375
|
+
json_response = @user_groups_interface.update(nil, user_group["id"], payload)
|
376
|
+
if options[:json]
|
377
|
+
puts as_json(json_response, options)
|
378
|
+
elsif !options[:quiet]
|
379
|
+
if users.size == 1
|
380
|
+
print_green_success "Added #{users[0]['username']} to user group #{user_group['name']}"
|
381
|
+
else
|
382
|
+
print_green_success "Added #{users.size} users to user group #{user_group['name']}"
|
383
|
+
end
|
384
|
+
_get(user_group['id'], {})
|
385
|
+
end
|
386
|
+
return 0
|
387
|
+
rescue RestClient::Exception => e
|
388
|
+
print_rest_exception(e, options)
|
389
|
+
exit 1
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def remove_user(args)
|
394
|
+
options = {}
|
395
|
+
params = {}
|
396
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
397
|
+
opts.banner = subcommand_usage("[name] [user]")
|
398
|
+
build_common_options(opts, options, [:json, :dry_run, :remote, :quiet])
|
399
|
+
opts.footer = "Remove a user from a user group.\n" +
|
400
|
+
"[name] is required. This is the name or id of a user group.\n" +
|
401
|
+
"[user] is required. This is the username or id of a user. More than one can be passed."
|
402
|
+
end
|
403
|
+
optparse.parse!(args)
|
404
|
+
if args.count < 2
|
405
|
+
puts optparse
|
406
|
+
return 1
|
407
|
+
end
|
408
|
+
connect(options)
|
409
|
+
begin
|
410
|
+
user_group = find_user_group_by_name_or_id(nil, args[0])
|
411
|
+
if user_group.nil?
|
412
|
+
return 1
|
413
|
+
end
|
414
|
+
|
415
|
+
# construct payload
|
416
|
+
payload = nil
|
417
|
+
if options[:payload]
|
418
|
+
payload = options[:payload]
|
419
|
+
else
|
420
|
+
user_ids = args[1..-1]
|
421
|
+
users = []
|
422
|
+
user_ids.each do |user_id|
|
423
|
+
user = find_user_by_username_or_id(nil, user_id)
|
424
|
+
return 1 if user.nil?
|
425
|
+
users << user
|
426
|
+
end
|
427
|
+
remove_user_ids = users.collect {|it| it['id'] }
|
428
|
+
current_users = (user_group['users'] || [])
|
429
|
+
current_user_ids = current_users.collect {|it| it['id'] }
|
430
|
+
new_user_ids = (current_user_ids - remove_user_ids).uniq
|
431
|
+
user_group_payload = {} # user_group
|
432
|
+
user_group_payload['users'] = new_user_ids
|
433
|
+
payload = {'userGroup' => user_group_payload}
|
434
|
+
end
|
435
|
+
if options[:dry_run]
|
436
|
+
print_dry_run @user_groups_interface.dry.update(nil, user_group["id"], payload)
|
437
|
+
return 0
|
438
|
+
end
|
439
|
+
json_response = @user_groups_interface.update(nil, user_group["id"], payload)
|
440
|
+
if options[:json]
|
441
|
+
puts as_json(json_response, options)
|
442
|
+
elsif !options[:quiet]
|
443
|
+
if users.size == 1
|
444
|
+
print_green_success "Added #{users[0]['username']} to user group #{user_group['name']}"
|
445
|
+
else
|
446
|
+
print_green_success "Added #{users.size} users to user group #{user_group['name']}"
|
447
|
+
end
|
448
|
+
_get(user_group['id'], {})
|
449
|
+
end
|
450
|
+
return 0
|
451
|
+
rescue RestClient::Exception => e
|
452
|
+
print_rest_exception(e, options)
|
453
|
+
exit 1
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
def remove(args)
|
458
|
+
options = {}
|
459
|
+
params = {}
|
460
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
461
|
+
opts.banner = subcommand_usage("[name]")
|
462
|
+
build_common_options(opts, options, [:json, :dry_run, :quiet, :auto_confirm])
|
463
|
+
end
|
464
|
+
optparse.parse!(args)
|
465
|
+
if args.count < 1
|
466
|
+
puts optparse
|
467
|
+
return 127
|
468
|
+
end
|
469
|
+
connect(options)
|
470
|
+
|
471
|
+
begin
|
472
|
+
user_group = find_user_group_by_name_or_id(nil, args[0])
|
473
|
+
if user_group.nil?
|
474
|
+
return 1
|
475
|
+
end
|
476
|
+
|
477
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to delete user group '#{user_group['name']}'?", options)
|
478
|
+
return false
|
479
|
+
end
|
480
|
+
|
481
|
+
# payload = {
|
482
|
+
# 'userGroup' => {id: user_group["id"]}
|
483
|
+
# }
|
484
|
+
# payload['userGroup'].merge!(user_group)
|
485
|
+
payload = params
|
486
|
+
|
487
|
+
if options[:dry_run]
|
488
|
+
print_dry_run @user_groups_interface.dry.destroy(nil, user_group["id"])
|
489
|
+
return
|
490
|
+
end
|
491
|
+
|
492
|
+
json_response = @user_groups_interface.destroy(nil, user_group["id"])
|
493
|
+
if options[:json]
|
494
|
+
puts as_json(json_response, options)
|
495
|
+
elsif !options[:quiet]
|
496
|
+
print_green_success "Deleted user group #{user_group['name']}"
|
497
|
+
end
|
498
|
+
return 0, nil
|
499
|
+
rescue RestClient::Exception => e
|
500
|
+
print_rest_exception(e, options)
|
501
|
+
return 1
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
|
506
|
+
private
|
507
|
+
|
508
|
+
def print_user_groups_table(user_groups, opts={})
|
509
|
+
columns = [
|
510
|
+
{"ID" => lambda {|user_group| user_group['id'] } },
|
511
|
+
{"NAME" => lambda {|user_group| user_group['name'] } },
|
512
|
+
{"DESCRIPTION" => lambda {|user_group| user_group['description'] } },
|
513
|
+
{"USERS" => lambda {|user_group|
|
514
|
+
users = user_group['users']
|
515
|
+
if users
|
516
|
+
n_users = 3
|
517
|
+
if users.size > n_users
|
518
|
+
users.first(n_users).collect { |user| user['username'] }.join(", ") + ", (#{users.size - n_users} more)"
|
519
|
+
else
|
520
|
+
users.collect { |user| user['username'] }.join(", ")
|
521
|
+
end
|
522
|
+
else
|
523
|
+
""
|
524
|
+
end
|
525
|
+
} },
|
526
|
+
# {"KEY PAIR" => lambda {|user_group|
|
527
|
+
# user_group['keyPair'] ? user_group['keyPair']['name'] : user_group['sharedKeyPairId']
|
528
|
+
# } },
|
529
|
+
# {"SUDO" => lambda {|user_group| format_boolean(user_group['sudoUser']) } },
|
530
|
+
]
|
531
|
+
if opts[:include_fields]
|
532
|
+
columns = opts[:include_fields]
|
533
|
+
end
|
534
|
+
print as_pretty_table(user_groups, columns, opts)
|
535
|
+
end
|
536
|
+
|
537
|
+
def find_user_group_by_name_or_id(account_id, val)
|
538
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
539
|
+
return find_user_group_by_id(account_id, val)
|
540
|
+
else
|
541
|
+
return find_user_group_by_name(account_id, val)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
def find_user_group_by_id(account_id, id)
|
546
|
+
begin
|
547
|
+
json_response = @user_groups_interface.get(account_id, id.to_i)
|
548
|
+
return json_response['userGroup']
|
549
|
+
rescue RestClient::Exception => e
|
550
|
+
if e.response && e.response.code == 404
|
551
|
+
print_red_alert "User Group not found by id #{id}"
|
552
|
+
else
|
553
|
+
raise e
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
def find_user_group_by_name(account_id, name)
|
559
|
+
user_groups = @user_groups_interface.list(account_id, {name: name.to_s})['userGroups']
|
560
|
+
if user_groups.empty?
|
561
|
+
print_red_alert "User Group not found by name #{name}"
|
562
|
+
return nil
|
563
|
+
elsif user_groups.size > 1
|
564
|
+
print_red_alert "#{user_groups.size} user groups found by name #{name}"
|
565
|
+
print_user_groups_table(user_groups, {color: red})
|
566
|
+
print_red_alert "Try using ID instead"
|
567
|
+
print reset,"\n"
|
568
|
+
return nil
|
569
|
+
else
|
570
|
+
return user_groups[0]
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
end
|