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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +26 -0
  4. data/lib/morpheus/api/billing_interface.rb +34 -0
  5. data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
  6. data/lib/morpheus/api/deploy_interface.rb +1 -1
  7. data/lib/morpheus/api/deployments_interface.rb +20 -1
  8. data/lib/morpheus/api/forgot_password_interface.rb +17 -0
  9. data/lib/morpheus/api/instances_interface.rb +7 -0
  10. data/lib/morpheus/api/rest_interface.rb +0 -6
  11. data/lib/morpheus/api/roles_interface.rb +14 -0
  12. data/lib/morpheus/api/search_interface.rb +13 -0
  13. data/lib/morpheus/api/servers_interface.rb +7 -0
  14. data/lib/morpheus/api/usage_interface.rb +18 -0
  15. data/lib/morpheus/cli.rb +6 -3
  16. data/lib/morpheus/cli/apps.rb +3 -4
  17. data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
  18. data/lib/morpheus/cli/backups_command.rb +3 -0
  19. data/lib/morpheus/cli/budgets_command.rb +4 -4
  20. data/lib/morpheus/cli/catalog_command.rb +507 -0
  21. data/lib/morpheus/cli/cli_command.rb +45 -20
  22. data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
  23. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
  24. data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
  25. data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
  26. data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
  27. data/lib/morpheus/cli/containers_command.rb +14 -0
  28. data/lib/morpheus/cli/deploy.rb +199 -90
  29. data/lib/morpheus/cli/deployments.rb +342 -29
  30. data/lib/morpheus/cli/deploys.rb +206 -41
  31. data/lib/morpheus/cli/error_handler.rb +7 -0
  32. data/lib/morpheus/cli/forgot_password.rb +133 -0
  33. data/lib/morpheus/cli/groups.rb +1 -1
  34. data/lib/morpheus/cli/health_command.rb +2 -2
  35. data/lib/morpheus/cli/hosts.rb +181 -26
  36. data/lib/morpheus/cli/instances.rb +102 -33
  37. data/lib/morpheus/cli/invoices_command.rb +33 -16
  38. data/lib/morpheus/cli/jobs_command.rb +28 -6
  39. data/lib/morpheus/cli/library_option_lists_command.rb +14 -6
  40. data/lib/morpheus/cli/logs_command.rb +9 -6
  41. data/lib/morpheus/cli/mixins/accounts_helper.rb +7 -6
  42. data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
  43. data/lib/morpheus/cli/mixins/catalog_helper.rb +66 -0
  44. data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
  45. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  46. data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
  47. data/lib/morpheus/cli/mixins/provisioning_helper.rb +24 -4
  48. data/lib/morpheus/cli/network_pools_command.rb +14 -6
  49. data/lib/morpheus/cli/option_types.rb +266 -17
  50. data/lib/morpheus/cli/ping.rb +0 -1
  51. data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
  52. data/lib/morpheus/cli/remote.rb +35 -12
  53. data/lib/morpheus/cli/reports_command.rb +99 -30
  54. data/lib/morpheus/cli/roles.rb +305 -3
  55. data/lib/morpheus/cli/search_command.rb +182 -0
  56. data/lib/morpheus/cli/service_plans_command.rb +2 -2
  57. data/lib/morpheus/cli/setup.rb +1 -1
  58. data/lib/morpheus/cli/shell.rb +33 -11
  59. data/lib/morpheus/cli/storage_providers_command.rb +40 -56
  60. data/lib/morpheus/cli/tasks.rb +20 -21
  61. data/lib/morpheus/cli/tenants_command.rb +1 -1
  62. data/lib/morpheus/cli/usage_command.rb +203 -0
  63. data/lib/morpheus/cli/user_settings_command.rb +1 -0
  64. data/lib/morpheus/cli/users.rb +12 -1
  65. data/lib/morpheus/cli/version.rb +1 -1
  66. data/lib/morpheus/cli/virtual_images.rb +280 -199
  67. data/lib/morpheus/cli/whoami.rb +6 -6
  68. data/lib/morpheus/cli/workflows.rb +34 -41
  69. data/lib/morpheus/formatters.rb +48 -5
  70. data/lib/morpheus/terminal.rb +6 -2
  71. metadata +13 -2
@@ -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
  ]
@@ -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, see the command `remote list`.
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
- Also, instead of using an active remote, the -r option can be specified in your commands.
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
- # appliance = load_remote_by_name("current")
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, :types
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
- it['fieldContext'] = nil
276
- it
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 types(args)
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
- build_common_options(opts, options, [:list, :json, :dry_run, :remote])
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
- begin
479
- params = {}
480
- params.merge!(parse_list_options(options))
481
-
482
- @reports_interface.setopts(options)
483
- if options[:dry_run]
484
- print_dry_run @reports_interface.dry.types(params)
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
- return 0
524
- rescue RestClient::Exception => e
525
- print_rest_exception(e, options)
526
- exit 1
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.list({max: 1000})['reportTypes'] || []
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.list({max: 1000})['reportTypes'] || []
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}"
@@ -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('-a','--all-access', "Display All Access Lists") do
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
- print reset,"\n"
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