morpheus-cli 4.2.20 → 5.0.2
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/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +26 -0
- data/lib/morpheus/api/billing_interface.rb +34 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
- data/lib/morpheus/api/deploy_interface.rb +1 -1
- data/lib/morpheus/api/deployments_interface.rb +20 -1
- data/lib/morpheus/api/forgot_password_interface.rb +17 -0
- data/lib/morpheus/api/instances_interface.rb +7 -0
- data/lib/morpheus/api/rest_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +6 -3
- data/lib/morpheus/cli/apps.rb +3 -4
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/budgets_command.rb +4 -4
- data/lib/morpheus/cli/catalog_command.rb +507 -0
- data/lib/morpheus/cli/cli_command.rb +45 -20
- data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
- data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
- data/lib/morpheus/cli/containers_command.rb +14 -0
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +342 -29
- data/lib/morpheus/cli/deploys.rb +206 -41
- data/lib/morpheus/cli/error_handler.rb +7 -0
- data/lib/morpheus/cli/forgot_password.rb +133 -0
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/health_command.rb +2 -2
- data/lib/morpheus/cli/hosts.rb +181 -26
- data/lib/morpheus/cli/instances.rb +102 -33
- data/lib/morpheus/cli/invoices_command.rb +33 -16
- data/lib/morpheus/cli/jobs_command.rb +28 -6
- data/lib/morpheus/cli/library_option_lists_command.rb +14 -6
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +7 -6
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- data/lib/morpheus/cli/mixins/catalog_helper.rb +66 -0
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +24 -4
- data/lib/morpheus/cli/network_pools_command.rb +14 -6
- data/lib/morpheus/cli/option_types.rb +266 -17
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +35 -12
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +305 -3
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/storage_providers_command.rb +40 -56
- data/lib/morpheus/cli/tasks.rb +20 -21
- data/lib/morpheus/cli/tenants_command.rb +1 -1
- data/lib/morpheus/cli/usage_command.rb +203 -0
- data/lib/morpheus/cli/user_settings_command.rb +1 -0
- data/lib/morpheus/cli/users.rb +12 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +280 -199
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +34 -41
- data/lib/morpheus/formatters.rb +48 -5
- data/lib/morpheus/terminal.rb +6 -2
- metadata +13 -2
data/lib/morpheus/cli/ping.rb
CHANGED
@@ -199,7 +199,6 @@ EOT
|
|
199
199
|
"Version" => lambda {|it| appliance[:build_version] },
|
200
200
|
# "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
|
201
201
|
"Response Time" => lambda {|it| format_duration_seconds(took_sec) },
|
202
|
-
#"Response Time" => lambda {|it| format_sig_dig(took_sec, 3) + "s" rescue "" },
|
203
202
|
# "Error" => lambda {|it| error_string },
|
204
203
|
"Status" => lambda {|it| format_appliance_status(appliance, cyan) },
|
205
204
|
}
|
@@ -478,7 +478,7 @@ class Morpheus::Cli::ProvisioningLicensesCommand
|
|
478
478
|
|
479
479
|
def add_license_option_types
|
480
480
|
[
|
481
|
-
{'fieldName' => 'licenseType', 'fieldLabel' => 'License Type', 'type' => 'select', 'optionSource' => lambda {
|
481
|
+
{'fieldName' => 'licenseType', 'fieldLabel' => 'License Type', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
482
482
|
# @options_interface.options_for_source("licenseTypes", {})['data']
|
483
483
|
get_license_types_dropdown()
|
484
484
|
}, 'required' => true, 'displayOrder' => 1},
|
@@ -493,7 +493,7 @@ class Morpheus::Cli::ProvisioningLicensesCommand
|
|
493
493
|
# @options_interface.options_for_source("virtualImages", {})['data']
|
494
494
|
get_virtual_images_dropdown()
|
495
495
|
}, 'displayOrder' => 9},
|
496
|
-
{'fieldName' => 'tenants', 'fieldLabel' => 'Tenants', 'type' => 'multiSelect', 'optionSource' => lambda {
|
496
|
+
{'fieldName' => 'tenants', 'fieldLabel' => 'Tenants', 'type' => 'multiSelect', 'optionSource' => lambda { |api_client, api_params|
|
497
497
|
@options_interface.options_for_source("allTenants", {})['data']
|
498
498
|
}, 'displayOrder' => 10},
|
499
499
|
]
|
data/lib/morpheus/cli/remote.rb
CHANGED
@@ -23,6 +23,8 @@ class Morpheus::Cli::Remote
|
|
23
23
|
|
24
24
|
set_default_subcommand :list
|
25
25
|
|
26
|
+
set_subcommands_hidden :setup # this is going away too
|
27
|
+
|
26
28
|
def initialize()
|
27
29
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
28
30
|
end
|
@@ -137,7 +139,6 @@ EOT
|
|
137
139
|
check_str
|
138
140
|
},
|
139
141
|
"Response Time" => lambda {|it| format_duration_milliseconds(it[:last_check][:took]) rescue "" },
|
140
|
-
#"Response Time" => lambda {|it| format_sig_dig((it[:last_check][:took]/ 1000.to_f), 3) + "s" rescue "" },
|
141
142
|
"Error" => {display_method: lambda {|it|
|
142
143
|
error_str = it[:last_check] ? it[:last_check][:error].to_s : ""
|
143
144
|
error_str
|
@@ -596,7 +597,7 @@ EOT
|
|
596
597
|
if args.count != 0
|
597
598
|
raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
598
599
|
end
|
599
|
-
connect(options) # needed?
|
600
|
+
#connect(options) # needed?
|
600
601
|
_check_all_appliances(options)
|
601
602
|
end
|
602
603
|
|
@@ -827,6 +828,12 @@ EOT
|
|
827
828
|
options[:do_offline] = true
|
828
829
|
end
|
829
830
|
build_common_options(opts, options, [:json,:yaml,:csv,:fields, :quiet])
|
831
|
+
opts.footer = <<-EOT
|
832
|
+
Print details about the a remote appliance.
|
833
|
+
[name] is optional. This is the name of a remote.
|
834
|
+
By default, the current appliance is used.
|
835
|
+
Returns an error if the specified remote is not found, or there is no current remote.
|
836
|
+
EOT
|
830
837
|
end
|
831
838
|
optparse.parse!(args)
|
832
839
|
id_list = nil
|
@@ -844,7 +851,16 @@ EOT
|
|
844
851
|
|
845
852
|
def _get(appliance_name, options)
|
846
853
|
exit_code, err = 0, nil
|
847
|
-
|
854
|
+
if appliance_name == 'current'
|
855
|
+
current_appliance = ::Morpheus::Cli::Remote.load_active_remote()
|
856
|
+
if current_appliance.nil?
|
857
|
+
#raise_command_error "No current appliance, see the command `remote use`"
|
858
|
+
unless options[:quiet]
|
859
|
+
print yellow, "No current appliance, see the command `remote use`", reset, "\n"
|
860
|
+
end
|
861
|
+
return 1, "No current appliance"
|
862
|
+
end
|
863
|
+
end
|
848
864
|
appliance = load_remote_by_name(appliance_name)
|
849
865
|
appliance_name = appliance[:name]
|
850
866
|
appliance_url = appliance[:url]
|
@@ -1040,15 +1056,14 @@ EOT
|
|
1040
1056
|
end
|
1041
1057
|
build_common_options(opts, options, [:quiet])
|
1042
1058
|
opts.footer = <<-EOT
|
1043
|
-
[name] is required. This is the name of a remote
|
1059
|
+
[name] is required. This is the name of a remote to begin using.
|
1044
1060
|
Start using a remote, making it the active (current) remote appliance.
|
1045
1061
|
This switches the remote context of your client configuration for all subsequent commands.
|
1046
|
-
So rely on 'remote use' with caution.
|
1047
1062
|
It is important to always be aware of the context your commands are running in.
|
1048
1063
|
The command `remote current` will return the current remote information.
|
1049
|
-
|
1064
|
+
Instead of using an active remote, the -r option can be specified with each command.
|
1050
1065
|
|
1051
|
-
It is recommeneded to set a custom prompt to show the remote name.
|
1066
|
+
It is recommeneded to set a custom prompt to show the current remote name.
|
1052
1067
|
For example, add the following to your .morpheusrc file:
|
1053
1068
|
|
1054
1069
|
# set your shell prompt to display the current username and remote
|
@@ -1156,13 +1171,22 @@ EOT
|
|
1156
1171
|
end
|
1157
1172
|
optparse.parse!(args)
|
1158
1173
|
verify_args!(args:args, count:0, optparse:optparse)
|
1159
|
-
connect(options)
|
1174
|
+
#connect(options)
|
1175
|
+
|
1176
|
+
current_appliance = ::Morpheus::Cli::Remote.load_active_remote()
|
1177
|
+
if current_appliance.nil?
|
1178
|
+
#raise_command_error "No current appliance, see the command `remote use`"
|
1179
|
+
unless options[:quiet]
|
1180
|
+
print yellow, "No current appliance, see the command `remote use`", reset, "\n"
|
1181
|
+
end
|
1182
|
+
return 1, "No current appliance"
|
1183
|
+
end
|
1160
1184
|
|
1161
1185
|
# this does the same thing
|
1162
1186
|
#return _get("current", options)
|
1163
|
-
|
1164
|
-
#
|
1165
|
-
appliance = @remote_appliance
|
1187
|
+
appliance = current_appliance
|
1188
|
+
#appliance = load_remote_by_name("current")
|
1189
|
+
#appliance = @remote_appliance
|
1166
1190
|
exit_code, err = 0, nil
|
1167
1191
|
if appliance.nil?
|
1168
1192
|
raise_command_error "no current remote appliance, see command `remote add`."
|
@@ -1283,7 +1307,6 @@ EOT
|
|
1283
1307
|
end
|
1284
1308
|
},
|
1285
1309
|
"Response Time" => lambda {|it| format_duration_milliseconds(it[:last_check][:took]) rescue "" },
|
1286
|
-
#"Response Time" => lambda {|it| format_sig_dig((it[:last_check][:took]/ 1000.to_f), 3) + "s" rescue "" },
|
1287
1310
|
"Status" => lambda {|it| format_appliance_status(it, cyan) },
|
1288
1311
|
"Error" => lambda {|it|
|
1289
1312
|
error_str = it[:last_check] ? it[:last_check][:error] : ""
|
@@ -15,7 +15,10 @@ class Morpheus::Cli::ReportsCommand
|
|
15
15
|
@reports_interface = @api_client.reports
|
16
16
|
end
|
17
17
|
|
18
|
-
register_subcommands :list, :get, :run, :view, :export, :remove
|
18
|
+
register_subcommands :list, :get, :run, :view, :export, :remove
|
19
|
+
register_subcommands :'list-types' => :list_types
|
20
|
+
register_subcommands :'get-type' => :get_type
|
21
|
+
alias_subcommand :types, :'list-types'
|
19
22
|
|
20
23
|
def default_refresh_interval
|
21
24
|
5
|
@@ -271,10 +274,10 @@ class Morpheus::Cli::ReportsCommand
|
|
271
274
|
|
272
275
|
# Report Types tell us what the available filters are...
|
273
276
|
report_option_types = report_type['optionTypes'] || []
|
274
|
-
report_option_types = report_option_types.collect {|it|
|
275
|
-
|
276
|
-
|
277
|
-
}
|
277
|
+
# report_option_types = report_option_types.collect {|it|
|
278
|
+
# it['fieldContext'] = nil
|
279
|
+
# it
|
280
|
+
# }
|
278
281
|
# pluck out optionTypes like the UI does..
|
279
282
|
metadata_option_type = nil
|
280
283
|
if report_option_types.find {|it| it['fieldName'] == 'metadata' }
|
@@ -284,6 +287,13 @@ class Morpheus::Cli::ReportsCommand
|
|
284
287
|
v_prompt = Morpheus::Cli::OptionTypes.prompt(report_option_types, options[:options], @api_client)
|
285
288
|
payload.deep_merge!({'report' => v_prompt}) unless v_prompt.empty?
|
286
289
|
|
290
|
+
# strip out fieldContext: 'config' please
|
291
|
+
# just report.startDate instead of report.config.startDate
|
292
|
+
if payload['report']['config'].is_a?(Hash)
|
293
|
+
payload['report']['config']
|
294
|
+
payload['report'].deep_merge!(payload['report'].delete('config'))
|
295
|
+
end
|
296
|
+
|
287
297
|
if metadata_option_type
|
288
298
|
if !options[:options]['metadata']
|
289
299
|
metadata_filter = prompt_metadata(options)
|
@@ -466,33 +476,30 @@ class Morpheus::Cli::ReportsCommand
|
|
466
476
|
end
|
467
477
|
end
|
468
478
|
|
469
|
-
def
|
479
|
+
def list_types(args)
|
480
|
+
params = {}
|
470
481
|
options = {}
|
471
482
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
472
483
|
opts.banner = subcommand_usage()
|
473
|
-
|
484
|
+
build_standard_list_options(opts, options)
|
474
485
|
opts.footer = "List report types."
|
475
486
|
end
|
476
487
|
optparse.parse!(args)
|
488
|
+
if args.count > 0
|
489
|
+
options[:phrase] = args.join(" ")
|
490
|
+
end
|
477
491
|
connect(options)
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
@reports_interface.
|
483
|
-
|
484
|
-
|
485
|
-
return
|
486
|
-
end
|
487
|
-
|
488
|
-
json_response = @reports_interface.types(params)
|
489
|
-
if options[:json]
|
490
|
-
print JSON.pretty_generate(json_response)
|
491
|
-
print "\n"
|
492
|
-
return
|
493
|
-
end
|
494
|
-
|
492
|
+
params.merge!(parse_list_options(options))
|
493
|
+
|
494
|
+
@reports_interface.setopts(options)
|
495
|
+
if options[:dry_run]
|
496
|
+
print_dry_run @reports_interface.dry.types(params)
|
497
|
+
return
|
498
|
+
end
|
495
499
|
|
500
|
+
json_response = @reports_interface.types(params)
|
501
|
+
report_types = json_response['reportTypes']
|
502
|
+
render_response(json_response, options, 'reportTypes') do
|
496
503
|
title = "Morpheus Report Types"
|
497
504
|
subtitles = []
|
498
505
|
subtitles += parse_list_subtitles(options)
|
@@ -520,13 +527,75 @@ class Morpheus::Cli::ReportsCommand
|
|
520
527
|
end
|
521
528
|
end
|
522
529
|
print reset,"\n"
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
530
|
+
end
|
531
|
+
if report_types.empty?
|
532
|
+
return 1, "no report types found"
|
533
|
+
else
|
534
|
+
return 0, nil
|
527
535
|
end
|
528
536
|
end
|
529
537
|
|
538
|
+
def get_type(args)
|
539
|
+
params = {}
|
540
|
+
options = {}
|
541
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
542
|
+
opts.banner = subcommand_usage()
|
543
|
+
build_standard_get_options(opts, options)
|
544
|
+
opts.footer = <<-EOT
|
545
|
+
Get report type
|
546
|
+
[name] is required. This is the name of a report type
|
547
|
+
EOT
|
548
|
+
end
|
549
|
+
optparse.parse!(args)
|
550
|
+
connect(options)
|
551
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
552
|
+
params.merge!(parse_query_options(options))
|
553
|
+
params['name'] = args.join(" ")
|
554
|
+
@reports_interface.setopts(options)
|
555
|
+
if options[:dry_run]
|
556
|
+
print_dry_run @reports_interface.dry.types(params)
|
557
|
+
return
|
558
|
+
end
|
559
|
+
|
560
|
+
# json_response = @reports_interface.types(params)
|
561
|
+
# api does not have a show() action right now... so find by code or name only
|
562
|
+
report_type = find_report_type_by_name_or_code_id(params['name'])
|
563
|
+
return 1 if report_type.nil?
|
564
|
+
|
565
|
+
# json_response = @reports_interface.get_type(report_type['id'])
|
566
|
+
# report_type = json_response['reportType']
|
567
|
+
json_response = {'reportType' => report_type}
|
568
|
+
render_response(json_response, options, 'reportType') do
|
569
|
+
print_h1 "Report Type Details", [], options
|
570
|
+
|
571
|
+
description_cols = {
|
572
|
+
"ID" => 'id',
|
573
|
+
"Name" => 'name',
|
574
|
+
"Code" => 'code',
|
575
|
+
"Description" => 'description',
|
576
|
+
"Category" => 'category'
|
577
|
+
}
|
578
|
+
print_description_list(description_cols, report_type)
|
579
|
+
|
580
|
+
print_h2 "Option Types", options
|
581
|
+
opt_columns = [
|
582
|
+
{"ID" => lambda {|it| it['id'] } },
|
583
|
+
{"NAME" => lambda {|it| it['name'] } },
|
584
|
+
{"TYPE" => lambda {|it| it['type'] } },
|
585
|
+
{"FIELD NAME" => lambda {|it| it['fieldName'] } },
|
586
|
+
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
587
|
+
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
588
|
+
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
589
|
+
]
|
590
|
+
option_types = report_type['optionTypes']
|
591
|
+
sorted_option_types = (option_types && option_types[0] && option_types[0]['displayOrder']) ? option_types.sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i } : option_types
|
592
|
+
print as_pretty_table(sorted_option_types, opt_columns)
|
593
|
+
|
594
|
+
print reset,"\n"
|
595
|
+
end
|
596
|
+
return 0, nil
|
597
|
+
|
598
|
+
end
|
530
599
|
|
531
600
|
def find_report_result_by_id(id)
|
532
601
|
begin
|
@@ -551,7 +620,7 @@ class Morpheus::Cli::ReportsCommand
|
|
551
620
|
end
|
552
621
|
|
553
622
|
def find_report_type_by_id(id)
|
554
|
-
@all_report_types ||= @reports_interface.
|
623
|
+
@all_report_types ||= @reports_interface.types({max: 10000})['reportTypes'] || []
|
555
624
|
report_types = @all_report_types.select { |it| id && it['id'] == id.to_i }
|
556
625
|
if report_types.empty?
|
557
626
|
print_red_alert "Report Type not found by id #{id}"
|
@@ -570,7 +639,7 @@ class Morpheus::Cli::ReportsCommand
|
|
570
639
|
end
|
571
640
|
|
572
641
|
def find_report_type_by_name_or_code(name)
|
573
|
-
@all_report_types ||= @reports_interface.
|
642
|
+
@all_report_types ||= @reports_interface.types({max: 10000})['reportTypes'] || []
|
574
643
|
report_types = @all_report_types.select { |it| name && it['code'] == name || it['name'] == name }
|
575
644
|
if report_types.empty?
|
576
645
|
print_red_alert "Report Type not found by code #{name}"
|
data/lib/morpheus/cli/roles.rb
CHANGED
@@ -13,7 +13,7 @@ class Morpheus::Cli::Roles
|
|
13
13
|
include Morpheus::Cli::AccountsHelper
|
14
14
|
include Morpheus::Cli::ProvisioningHelper
|
15
15
|
include Morpheus::Cli::WhoamiHelper
|
16
|
-
register_subcommands :list, :get, :add, :update, :remove, :'list-permissions', :'update-feature-access', :'update-global-group-access', :'update-group-access', :'update-global-cloud-access', :'update-cloud-access', :'update-global-instance-type-access', :'update-instance-type-access', :'update-global-blueprint-access', :'update-blueprint-access'
|
16
|
+
register_subcommands :list, :get, :add, :update, :remove, :'list-permissions', :'update-feature-access', :'update-global-group-access', :'update-group-access', :'update-global-cloud-access', :'update-cloud-access', :'update-global-instance-type-access', :'update-instance-type-access', :'update-global-blueprint-access', :'update-blueprint-access', :'update-global-catalog-item-type-access', :'update-catalog-item-type-access', :'update-persona-access'
|
17
17
|
alias_subcommand :details, :get
|
18
18
|
set_default_subcommand :list
|
19
19
|
|
@@ -101,12 +101,20 @@ class Morpheus::Cli::Roles
|
|
101
101
|
opts.on('-b','--blueprint-access', "Display Blueprint Access") do
|
102
102
|
options[:include_blueprint_access] = true
|
103
103
|
end
|
104
|
-
opts.on(
|
104
|
+
opts.on(nil,'--catalog-item-type-access', "Display Catalog Item Type Access") do
|
105
|
+
options[:include_catalog_item_types_access] = true
|
106
|
+
end
|
107
|
+
opts.on(nil,'--personas', "Display Persona Access") do
|
108
|
+
options[:include_personas_access] = true
|
109
|
+
end
|
110
|
+
opts.on('-a','--all', "Display All Access Lists") do
|
105
111
|
options[:include_feature_access] = true
|
106
112
|
options[:include_group_access] = true
|
107
113
|
options[:include_cloud_access] = true
|
108
114
|
options[:include_instance_type_access] = true
|
109
115
|
options[:include_blueprint_access] = true
|
116
|
+
options[:include_catalog_item_types_access] = true
|
117
|
+
options[:include_personas_access] = true
|
110
118
|
end
|
111
119
|
build_standard_get_options(opts, options)
|
112
120
|
opts.footer = <<-EOT
|
@@ -198,6 +206,7 @@ EOT
|
|
198
206
|
rows = rows.select {|row| row[:code].to_s =~ phrase_regexp || row[:name].to_s =~ phrase_regexp }
|
199
207
|
end
|
200
208
|
print as_pretty_table(rows, [:code, :name, :access], options)
|
209
|
+
print reset,"\n"
|
201
210
|
else
|
202
211
|
print cyan,"Use --permissions to list permissions","\n"
|
203
212
|
end
|
@@ -208,6 +217,7 @@ EOT
|
|
208
217
|
{"Clouds" => lambda {|it| get_access_string(it['globalZoneAccess']) } },
|
209
218
|
{"Instance Types" => lambda {|it| get_access_string(it['globalInstanceTypeAccess']) } },
|
210
219
|
{"Blueprints" => lambda {|it| get_access_string(it['globalAppTemplateAccess'] || it['globalBlueprintAccess']) } },
|
220
|
+
{"Catalog Item Types" => lambda {|it| get_access_string(it['globalCatalogItemTypeAccess']) } },
|
211
221
|
], options)
|
212
222
|
|
213
223
|
#print_h2 "Group Access: #{get_access_string(json_response['globalSiteAccess'])}", options
|
@@ -225,6 +235,7 @@ EOT
|
|
225
235
|
else
|
226
236
|
print cyan,"Use -g, --group-access to list custom access","\n"
|
227
237
|
end
|
238
|
+
print reset,"\n"
|
228
239
|
else
|
229
240
|
# print "\n"
|
230
241
|
# print cyan,bold,"Group Access: #{get_access_string(json_response['globalSiteAccess'])}",reset,"\n"
|
@@ -246,6 +257,7 @@ EOT
|
|
246
257
|
else
|
247
258
|
print cyan,"Use -c, --cloud-access to list custom access","\n"
|
248
259
|
end
|
260
|
+
print reset,"\n"
|
249
261
|
else
|
250
262
|
# print "\n"
|
251
263
|
# print cyan,bold,"Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}",reset,"\n"
|
@@ -267,6 +279,7 @@ EOT
|
|
267
279
|
else
|
268
280
|
print cyan,"Use -i, --instance-type-access to list custom access","\n"
|
269
281
|
end
|
282
|
+
print reset,"\n"
|
270
283
|
else
|
271
284
|
# print "\n"
|
272
285
|
# print cyan,bold,"Instance Type Access: #{get_access_string(json_response['globalInstanceTypeAccess'])}",reset,"\n"
|
@@ -290,12 +303,54 @@ EOT
|
|
290
303
|
else
|
291
304
|
print cyan,"Use -b, --blueprint-access to list custom access","\n"
|
292
305
|
end
|
306
|
+
print reset,"\n"
|
293
307
|
else
|
294
308
|
# print "\n"
|
295
309
|
# print cyan,bold,"Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}",reset,"\n"
|
296
310
|
end
|
297
|
-
|
311
|
+
|
312
|
+
|
313
|
+
catalog_item_type_global_access = json_response['globalCatalogItemTypeAccess']
|
314
|
+
catalog_item_type_permissions = json_response['catalogItemTypePermissions'] || []
|
315
|
+
print cyan
|
316
|
+
# print_h2 "catalog_item_type Access: #{get_access_string(json_response['globalCatalogItemTypeAccess'])}", options
|
317
|
+
# print "\n"
|
318
|
+
if catalog_item_type_global_access == 'custom'
|
319
|
+
print_h2 "Catalog Item Type Access", options
|
320
|
+
if options[:include_catalog_item_types_access]
|
321
|
+
rows = catalog_item_type_permissions.collect do |it|
|
322
|
+
{
|
323
|
+
name: it['name'],
|
324
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
325
|
+
}
|
326
|
+
end
|
327
|
+
print as_pretty_table(rows, [:name, :access], options)
|
328
|
+
else
|
329
|
+
print cyan,"Use -b, --catalog-item-type-access to list custom access","\n"
|
330
|
+
end
|
331
|
+
else
|
332
|
+
# print "\n"
|
333
|
+
# print cyan,bold,"Catalog Item Type Access: #{get_access_string(json_response['globalCatalogItemTypeAccess'])}",reset,"\n"
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
persona_permissions = json_response['personaPermissions'] || json_response['personas'] || []
|
338
|
+
if options[:include_catalog_item_types_access]
|
339
|
+
print_h2 "Persona Access", options
|
340
|
+
rows = persona_permissions.collect do |it|
|
341
|
+
{
|
342
|
+
name: it['name'],
|
343
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
344
|
+
}
|
345
|
+
end
|
346
|
+
print as_pretty_table(rows, [:name, :access], options)
|
347
|
+
print reset,"\n"
|
348
|
+
end
|
349
|
+
|
350
|
+
# print reset,"\n"
|
351
|
+
|
298
352
|
end
|
353
|
+
|
299
354
|
return 0, nil
|
300
355
|
end
|
301
356
|
|
@@ -449,6 +504,10 @@ EOT
|
|
449
504
|
end
|
450
505
|
end
|
451
506
|
|
507
|
+
# v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'optionSource' => 'personas', 'description' => 'Default Persona'}], options[:options], @api_client)
|
508
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => [{'name'=>'Service Catalog','value'=>'serviceCatalog'},{'name'=>'Standard','value'=>'standard'}], 'description' => 'Default Persona'}], options[:options], @api_client)
|
509
|
+
role_payload['defaultPersona'] = {'code' => v_prompt['defaultPersona']} unless v_prompt['defaultPersona'].to_s.strip.empty?
|
510
|
+
|
452
511
|
payload = {"role" => role_payload}
|
453
512
|
end
|
454
513
|
@roles_interface.setopts(options)
|
@@ -1267,6 +1326,249 @@ EOT
|
|
1267
1326
|
end
|
1268
1327
|
end
|
1269
1328
|
|
1329
|
+
def update_global_catalog_item_type_access(args)
|
1330
|
+
usage = "Usage: morpheus roles update-global-catalog-item-type-access [name] [full|custom|none]"
|
1331
|
+
options = {}
|
1332
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1333
|
+
opts.banner = subcommand_usage("[name] [full|custom|none]")
|
1334
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
1335
|
+
end
|
1336
|
+
optparse.parse!(args)
|
1337
|
+
|
1338
|
+
if args.count < 2
|
1339
|
+
puts optparse
|
1340
|
+
exit 1
|
1341
|
+
end
|
1342
|
+
name = args[0]
|
1343
|
+
access_value = args[1].to_s.downcase
|
1344
|
+
if !['full', 'custom', 'none'].include?(access_value)
|
1345
|
+
puts optparse
|
1346
|
+
exit 1
|
1347
|
+
end
|
1348
|
+
|
1349
|
+
|
1350
|
+
connect(options)
|
1351
|
+
begin
|
1352
|
+
account = find_account_from_options(options)
|
1353
|
+
account_id = account ? account['id'] : nil
|
1354
|
+
role = find_role_by_name_or_id(account_id, name)
|
1355
|
+
exit 1 if role.nil?
|
1356
|
+
|
1357
|
+
params = {permissionCode: 'CatalogItemType', access: access_value}
|
1358
|
+
@roles_interface.setopts(options)
|
1359
|
+
if options[:dry_run]
|
1360
|
+
print_dry_run @roles_interface.dry.update_permission(account_id, role['id'], params)
|
1361
|
+
return
|
1362
|
+
end
|
1363
|
+
json_response = @roles_interface.update_permission(account_id, role['id'], params)
|
1364
|
+
|
1365
|
+
if options[:json]
|
1366
|
+
print JSON.pretty_generate(json_response)
|
1367
|
+
print "\n"
|
1368
|
+
else
|
1369
|
+
print_green_success "Role #{role['authority']} global catalog item type access updated"
|
1370
|
+
end
|
1371
|
+
rescue RestClient::Exception => e
|
1372
|
+
print_rest_exception(e, options)
|
1373
|
+
exit 1
|
1374
|
+
end
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
def update_catalog_item_type_access(args)
|
1378
|
+
options = {}
|
1379
|
+
catalog_item_type_id = nil
|
1380
|
+
access_value = nil
|
1381
|
+
do_all = false
|
1382
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1383
|
+
opts.banner = subcommand_usage("[name]")
|
1384
|
+
opts.on( '--catalog-item-type ID', String, "Catalog Item Type ID or Name" ) do |val|
|
1385
|
+
catalog_item_type_id = val
|
1386
|
+
end
|
1387
|
+
opts.on( nil, '--all', "Update all catalog item types at once." ) do
|
1388
|
+
do_all = true
|
1389
|
+
end
|
1390
|
+
opts.on( '--access VALUE', String, "Access value [full|none]" ) do |val|
|
1391
|
+
access_value = val
|
1392
|
+
end
|
1393
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
1394
|
+
opts.footer = "Update role access for an catalog item type or all types.\n" +
|
1395
|
+
"[name] is required. This is the name or id of a role.\n" +
|
1396
|
+
"--catalog-item-type or --all is required. This is the name or id of a catalog item type.\n" +
|
1397
|
+
"--access is required. This is the new access value."
|
1398
|
+
end
|
1399
|
+
optparse.parse!(args)
|
1400
|
+
|
1401
|
+
if args.count < 1
|
1402
|
+
puts optparse
|
1403
|
+
return 1
|
1404
|
+
end
|
1405
|
+
name = args[0]
|
1406
|
+
# support old usage: [name] [catalog_item_type] [access]
|
1407
|
+
catalog_item_type_id ||= args[1]
|
1408
|
+
access_value ||= args[2]
|
1409
|
+
|
1410
|
+
if (!catalog_item_type_id && !do_all) || !access_value
|
1411
|
+
puts_error optparse
|
1412
|
+
return 1
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
access_value = access_value.to_s.downcase
|
1416
|
+
|
1417
|
+
if !['full', 'none'].include?(access_value)
|
1418
|
+
puts optparse
|
1419
|
+
return 1
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
connect(options)
|
1423
|
+
begin
|
1424
|
+
account = find_account_from_options(options)
|
1425
|
+
account_id = account ? account['id'] : nil
|
1426
|
+
role = find_role_by_name_or_id(account_id, name)
|
1427
|
+
return 1 if role.nil?
|
1428
|
+
|
1429
|
+
role_json = @roles_interface.get(account_id, role['id'])
|
1430
|
+
catalog_item_type_global_access = role_json['globalCatalogItemTypeAccess']
|
1431
|
+
catalog_item_type_permissions = role_json['catalogItemTypePermissions'] || []
|
1432
|
+
if catalog_item_type_global_access != 'custom'
|
1433
|
+
print "\n", red, "Global Catalog Item Type Access is currently: #{catalog_item_type_global_access.to_s.capitalize}"
|
1434
|
+
print "\n", "You must first set it to Custom via `morpheus roles update-global-catalog-item-type-access \"#{name}\" custom`"
|
1435
|
+
print "\n\n", reset
|
1436
|
+
return 1
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
# hacky, but support name or code lookup via the list returned in the show payload
|
1440
|
+
catalog_item_type = nil
|
1441
|
+
if !do_all
|
1442
|
+
if catalog_item_type_id.to_s =~ /\A\d{1,}\Z/
|
1443
|
+
catalog_item_type = catalog_item_type_permissions.find {|b| b['id'] == catalog_item_type_id.to_i }
|
1444
|
+
else
|
1445
|
+
catalog_item_type = catalog_item_type_permissions.find {|b| b['name'] == catalog_item_type_id }
|
1446
|
+
end
|
1447
|
+
if catalog_item_type.nil?
|
1448
|
+
print_red_alert "Catalog Item Type not found: '#{catalog_item_type_id}'"
|
1449
|
+
return 1
|
1450
|
+
end
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
params = {}
|
1454
|
+
if do_all
|
1455
|
+
params['allCatalogItemTypes'] = true
|
1456
|
+
else
|
1457
|
+
params['catalogItemTypeId'] = catalog_item_type['id']
|
1458
|
+
end
|
1459
|
+
params['access'] = access_value
|
1460
|
+
@roles_interface.setopts(options)
|
1461
|
+
if options[:dry_run]
|
1462
|
+
print_dry_run @roles_interface.dry.update_catalog_item_type(account_id, role['id'], params)
|
1463
|
+
return
|
1464
|
+
end
|
1465
|
+
json_response = @roles_interface.update_catalog_item_type(account_id, role['id'], params)
|
1466
|
+
|
1467
|
+
if options[:json]
|
1468
|
+
print JSON.pretty_generate(json_response)
|
1469
|
+
print "\n"
|
1470
|
+
else
|
1471
|
+
if do_all
|
1472
|
+
print_green_success "Role #{role['authority']} access updated for all catalog item types"
|
1473
|
+
else
|
1474
|
+
print_green_success "Role #{role['authority']} access updated for catalog item type #{catalog_item_type['name']}"
|
1475
|
+
end
|
1476
|
+
end
|
1477
|
+
return 0
|
1478
|
+
rescue RestClient::Exception => e
|
1479
|
+
print_rest_exception(e, options)
|
1480
|
+
exit 1
|
1481
|
+
end
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
def update_persona_access(args)
|
1485
|
+
options = {}
|
1486
|
+
persona_id = nil
|
1487
|
+
access_value = nil
|
1488
|
+
do_all = false
|
1489
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1490
|
+
opts.banner = subcommand_usage("[name] [serviceCatalog|standard]")
|
1491
|
+
opts.on( '--persona CODE', String, "Persona Code" ) do |val|
|
1492
|
+
persona_id = val
|
1493
|
+
end
|
1494
|
+
opts.on( nil, '--all', "Update all personas at once." ) do
|
1495
|
+
do_all = true
|
1496
|
+
end
|
1497
|
+
opts.on( '--access VALUE', String, "Access value [full|none]" ) do |val|
|
1498
|
+
access_value = val
|
1499
|
+
end
|
1500
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
1501
|
+
opts.footer = "Update role access for an persona or personas.\n" +
|
1502
|
+
"[name] is required. This is the name or id of a role.\n" +
|
1503
|
+
"--persona or --all is required. This is the code of a persona.\n" +
|
1504
|
+
"--access is required. This is the new access value."
|
1505
|
+
end
|
1506
|
+
optparse.parse!(args)
|
1507
|
+
|
1508
|
+
if args.count < 1
|
1509
|
+
puts optparse
|
1510
|
+
return 1
|
1511
|
+
end
|
1512
|
+
name = args[0]
|
1513
|
+
# support old usage: [name] [persona] [access]
|
1514
|
+
persona_id ||= args[1]
|
1515
|
+
access_value ||= args[2]
|
1516
|
+
|
1517
|
+
if (!persona_id && !do_all) || !access_value
|
1518
|
+
puts_error optparse
|
1519
|
+
return 1
|
1520
|
+
end
|
1521
|
+
|
1522
|
+
access_value = access_value.to_s.downcase
|
1523
|
+
|
1524
|
+
if !['full', 'none'].include?(access_value)
|
1525
|
+
puts optparse
|
1526
|
+
return 1
|
1527
|
+
end
|
1528
|
+
|
1529
|
+
connect(options)
|
1530
|
+
begin
|
1531
|
+
account = find_account_from_options(options)
|
1532
|
+
account_id = account ? account['id'] : nil
|
1533
|
+
role = find_role_by_name_or_id(account_id, name)
|
1534
|
+
return 1 if role.nil?
|
1535
|
+
|
1536
|
+
role_json = @roles_interface.get(account_id, role['id'])
|
1537
|
+
|
1538
|
+
# no lookup right now, pass the code serviceCatalog|standard
|
1539
|
+
persona_code = persona_id
|
1540
|
+
|
1541
|
+
params = {}
|
1542
|
+
if do_all
|
1543
|
+
params['allPersonas'] = true
|
1544
|
+
else
|
1545
|
+
params['personaCode'] = persona_code
|
1546
|
+
end
|
1547
|
+
params['access'] = access_value
|
1548
|
+
@roles_interface.setopts(options)
|
1549
|
+
if options[:dry_run]
|
1550
|
+
print_dry_run @roles_interface.dry.update_persona(account_id, role['id'], params)
|
1551
|
+
return
|
1552
|
+
end
|
1553
|
+
json_response = @roles_interface.update_persona(account_id, role['id'], params)
|
1554
|
+
|
1555
|
+
if options[:json]
|
1556
|
+
print JSON.pretty_generate(json_response)
|
1557
|
+
print "\n"
|
1558
|
+
else
|
1559
|
+
if do_all
|
1560
|
+
print_green_success "Role #{role['authority']} access updated for all personas"
|
1561
|
+
else
|
1562
|
+
print_green_success "Role #{role['authority']} access updated for persona #{persona_code}"
|
1563
|
+
end
|
1564
|
+
end
|
1565
|
+
return 0
|
1566
|
+
rescue RestClient::Exception => e
|
1567
|
+
print_rest_exception(e, options)
|
1568
|
+
exit 1
|
1569
|
+
end
|
1570
|
+
end
|
1571
|
+
|
1270
1572
|
private
|
1271
1573
|
|
1272
1574
|
def add_role_option_types
|