morpheus-cli 5.0.0 → 5.2.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Dockerfile +1 -1
  4. data/lib/morpheus/api/api_client.rb +16 -0
  5. data/lib/morpheus/api/billing_interface.rb +1 -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 +16 -2
  10. data/lib/morpheus/api/invoices_interface.rb +12 -3
  11. data/lib/morpheus/api/search_interface.rb +13 -0
  12. data/lib/morpheus/api/servers_interface.rb +14 -0
  13. data/lib/morpheus/api/service_catalog_interface.rb +89 -0
  14. data/lib/morpheus/api/usage_interface.rb +18 -0
  15. data/lib/morpheus/cli.rb +6 -2
  16. data/lib/morpheus/cli/apps.rb +3 -23
  17. data/lib/morpheus/cli/budgets_command.rb +389 -319
  18. data/lib/morpheus/cli/{catalog_command.rb → catalog_item_types_command.rb} +182 -67
  19. data/lib/morpheus/cli/cli_command.rb +51 -10
  20. data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -13
  21. data/lib/morpheus/cli/commands/standard/history_command.rb +9 -3
  22. data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
  23. data/lib/morpheus/cli/containers_command.rb +0 -24
  24. data/lib/morpheus/cli/cypher_command.rb +6 -2
  25. data/lib/morpheus/cli/dashboard_command.rb +260 -20
  26. data/lib/morpheus/cli/deploy.rb +199 -90
  27. data/lib/morpheus/cli/deployments.rb +341 -28
  28. data/lib/morpheus/cli/deploys.rb +206 -41
  29. data/lib/morpheus/cli/error_handler.rb +7 -0
  30. data/lib/morpheus/cli/forgot_password.rb +133 -0
  31. data/lib/morpheus/cli/groups.rb +1 -1
  32. data/lib/morpheus/cli/health_command.rb +59 -2
  33. data/lib/morpheus/cli/hosts.rb +271 -39
  34. data/lib/morpheus/cli/instances.rb +228 -129
  35. data/lib/morpheus/cli/invoices_command.rb +100 -20
  36. data/lib/morpheus/cli/jobs_command.rb +94 -92
  37. data/lib/morpheus/cli/library_option_lists_command.rb +1 -1
  38. data/lib/morpheus/cli/library_option_types_command.rb +10 -5
  39. data/lib/morpheus/cli/logs_command.rb +9 -6
  40. data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -1
  41. data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -2
  42. data/lib/morpheus/cli/mixins/print_helper.rb +13 -27
  43. data/lib/morpheus/cli/mixins/provisioning_helper.rb +108 -5
  44. data/lib/morpheus/cli/option_types.rb +271 -22
  45. data/lib/morpheus/cli/remote.rb +35 -10
  46. data/lib/morpheus/cli/reports_command.rb +99 -30
  47. data/lib/morpheus/cli/roles.rb +193 -155
  48. data/lib/morpheus/cli/search_command.rb +182 -0
  49. data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
  50. data/lib/morpheus/cli/setup.rb +1 -1
  51. data/lib/morpheus/cli/shell.rb +33 -11
  52. data/lib/morpheus/cli/tasks.rb +29 -32
  53. data/lib/morpheus/cli/usage_command.rb +64 -11
  54. data/lib/morpheus/cli/version.rb +1 -1
  55. data/lib/morpheus/cli/virtual_images.rb +429 -254
  56. data/lib/morpheus/cli/whoami.rb +6 -6
  57. data/lib/morpheus/cli/workflows.rb +33 -40
  58. data/lib/morpheus/formatters.rb +75 -18
  59. data/lib/morpheus/terminal.rb +6 -2
  60. metadata +10 -4
  61. data/lib/morpheus/cli/mixins/catalog_helper.rb +0 -66
@@ -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
@@ -595,7 +597,7 @@ EOT
595
597
  if args.count != 0
596
598
  raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
597
599
  end
598
- connect(options) # needed?
600
+ #connect(options) # needed?
599
601
  _check_all_appliances(options)
600
602
  end
601
603
 
@@ -826,6 +828,12 @@ EOT
826
828
  options[:do_offline] = true
827
829
  end
828
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
829
837
  end
830
838
  optparse.parse!(args)
831
839
  id_list = nil
@@ -843,7 +851,16 @@ EOT
843
851
 
844
852
  def _get(appliance_name, options)
845
853
  exit_code, err = 0, nil
846
-
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
847
864
  appliance = load_remote_by_name(appliance_name)
848
865
  appliance_name = appliance[:name]
849
866
  appliance_url = appliance[:url]
@@ -1039,15 +1056,14 @@ EOT
1039
1056
  end
1040
1057
  build_common_options(opts, options, [:quiet])
1041
1058
  opts.footer = <<-EOT
1042
- [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.
1043
1060
  Start using a remote, making it the active (current) remote appliance.
1044
1061
  This switches the remote context of your client configuration for all subsequent commands.
1045
- So rely on 'remote use' with caution.
1046
1062
  It is important to always be aware of the context your commands are running in.
1047
1063
  The command `remote current` will return the current remote information.
1048
- 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.
1049
1065
 
1050
- 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.
1051
1067
  For example, add the following to your .morpheusrc file:
1052
1068
 
1053
1069
  # set your shell prompt to display the current username and remote
@@ -1155,13 +1171,22 @@ EOT
1155
1171
  end
1156
1172
  optparse.parse!(args)
1157
1173
  verify_args!(args:args, count:0, optparse:optparse)
1158
- 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
1159
1184
 
1160
1185
  # this does the same thing
1161
1186
  #return _get("current", options)
1162
-
1163
- # appliance = load_remote_by_name("current")
1164
- appliance = @remote_appliance
1187
+ appliance = current_appliance
1188
+ #appliance = load_remote_by_name("current")
1189
+ #appliance = @remote_appliance
1165
1190
  exit_code, err = 0, nil
1166
1191
  if appliance.nil?
1167
1192
  raise_command_error "no current remote appliance, see command `remote add`."
@@ -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}"
@@ -211,56 +211,70 @@ EOT
211
211
  print cyan,"Use --permissions to list permissions","\n"
212
212
  end
213
213
 
214
+ has_group_access = true
215
+ has_cloud_access = true
214
216
  print_h2 "Global Access", options
215
- puts as_pretty_table([json_response], [
216
- {"Groups" => lambda {|it| get_access_string(it['globalSiteAccess']) } },
217
- {"Clouds" => lambda {|it| get_access_string(it['globalZoneAccess']) } },
218
- {"Instance Types" => lambda {|it| get_access_string(it['globalInstanceTypeAccess']) } },
219
- {"Blueprints" => lambda {|it| get_access_string(it['globalAppTemplateAccess'] || it['globalBlueprintAccess']) } },
220
- {"Catalog Item Types" => lambda {|it| get_access_string(it['globalCatalogItemTypeAccess']) } },
221
- ], options)
222
-
223
- #print_h2 "Group Access: #{get_access_string(json_response['globalSiteAccess'])}", options
224
- print cyan
225
- if json_response['globalSiteAccess'] == 'custom'
226
- print_h2 "Group Access", options
227
- if options[:include_group_access]
228
- rows = json_response['sites'].collect do |it|
229
- {
230
- name: it['name'],
231
- access: format_access_string(it['access'], ["none","read","full"]),
232
- }
217
+ global_access_columns = {
218
+ "Groups" => lambda {|it| get_access_string(it['globalSiteAccess']) },
219
+ "Clouds" => lambda {|it| get_access_string(it['globalZoneAccess']) },
220
+ "Instance Types" => lambda {|it| get_access_string(it['globalInstanceTypeAccess']) },
221
+ "Blueprints" => lambda {|it| get_access_string(it['globalAppTemplateAccess'] || it['globalBlueprintAccess']) },
222
+ "Catalog Item Types" => lambda {|it| get_access_string(it['globalCatalogItemTypeAccess']) },
223
+ }
224
+ if role['roleType'].to_s.downcase == 'account'
225
+ global_access_columns.delete("Groups")
226
+ has_group_access = false
227
+ else
228
+ global_access_columns.delete("Clouds")
229
+ has_cloud_access = false
230
+ end
231
+ puts as_pretty_table([json_response], global_access_columns, options)
232
+
233
+ if has_group_access
234
+ #print_h2 "Group Access: #{get_access_string(json_response['globalSiteAccess'])}", options
235
+ print cyan
236
+ if json_response['globalSiteAccess'] == 'custom'
237
+ print_h2 "Group Access", options
238
+ if options[:include_group_access]
239
+ rows = json_response['sites'].collect do |it|
240
+ {
241
+ name: it['name'],
242
+ access: format_access_string(it['access'], ["none","read","full"]),
243
+ }
244
+ end
245
+ print as_pretty_table(rows, [:name, :access], options)
246
+ else
247
+ print cyan,"Use -g, --group-access to list custom access","\n"
233
248
  end
234
- print as_pretty_table(rows, [:name, :access], options)
249
+ print reset,"\n"
235
250
  else
236
- print cyan,"Use -g, --group-access to list custom access","\n"
251
+ # print "\n"
252
+ # print cyan,bold,"Group Access: #{get_access_string(json_response['globalSiteAccess'])}",reset,"\n"
237
253
  end
238
- print reset,"\n"
239
- else
240
- # print "\n"
241
- # print cyan,bold,"Group Access: #{get_access_string(json_response['globalSiteAccess'])}",reset,"\n"
242
254
  end
243
255
 
244
- print cyan
245
- #puts "Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}"
246
- #print "\n"
247
- if json_response['globalZoneAccess'] == 'custom'
248
- print_h2 "Cloud Access", options
249
- if options[:include_cloud_access]
250
- rows = json_response['zones'].collect do |it|
251
- {
252
- name: it['name'],
253
- access: format_access_string(it['access'], ["none","read","full"]),
254
- }
256
+ if has_cloud_access
257
+ print cyan
258
+ #puts "Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}"
259
+ #print "\n"
260
+ if json_response['globalZoneAccess'] == 'custom'
261
+ print_h2 "Cloud Access", options
262
+ if options[:include_cloud_access]
263
+ rows = json_response['zones'].collect do |it|
264
+ {
265
+ name: it['name'],
266
+ access: format_access_string(it['access'], ["none","read","full"]),
267
+ }
268
+ end
269
+ print as_pretty_table(rows, [:name, :access], options)
270
+ else
271
+ print cyan,"Use -c, --cloud-access to list custom access","\n"
255
272
  end
256
- print as_pretty_table(rows, [:name, :access], options)
273
+ print reset,"\n"
257
274
  else
258
- print cyan,"Use -c, --cloud-access to list custom access","\n"
275
+ # print "\n"
276
+ # print cyan,bold,"Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}",reset,"\n"
259
277
  end
260
- print reset,"\n"
261
- else
262
- # print "\n"
263
- # print cyan,bold,"Cloud Access: #{get_access_string(json_response['globalZoneAccess'])}",reset,"\n"
264
278
  end
265
279
 
266
280
  print cyan
@@ -326,7 +340,7 @@ EOT
326
340
  end
327
341
  print as_pretty_table(rows, [:name, :access], options)
328
342
  else
329
- print cyan,"Use -b, --catalog-item-type-access to list custom access","\n"
343
+ print cyan,"Use --catalog-item-type-access to list custom access","\n"
330
344
  end
331
345
  else
332
346
  # print "\n"
@@ -335,7 +349,8 @@ EOT
335
349
 
336
350
 
337
351
  persona_permissions = json_response['personaPermissions'] || json_response['personas'] || []
338
- if options[:include_catalog_item_types_access]
352
+ # if options[:include_personas_access]
353
+ if persona_permissions
339
354
  print_h2 "Persona Access", options
340
355
  rows = persona_permissions.collect do |it|
341
356
  {
@@ -552,7 +567,7 @@ EOT
552
567
  options = {}
553
568
  params = {}
554
569
  optparse = Morpheus::Cli::OptionParser.new do |opts|
555
- opts.banner = subcommand_usage("[name] [options]")
570
+ opts.banner = subcommand_usage("[role] [options]")
556
571
  build_option_type_options(opts, options, update_role_option_types)
557
572
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
558
573
  end
@@ -630,7 +645,7 @@ EOT
630
645
  def remove(args)
631
646
  options = {}
632
647
  optparse = Morpheus::Cli::OptionParser.new do |opts|
633
- opts.banner = subcommand_usage("[name]")
648
+ opts.banner = subcommand_usage("[role]")
634
649
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
635
650
  end
636
651
  optparse.parse!(args)
@@ -770,41 +785,46 @@ EOT
770
785
  group_name = nil
771
786
  access_value = nil
772
787
  do_all = false
788
+ allowed_access_values = ['full', 'read', 'none']
773
789
  optparse = Morpheus::Cli::OptionParser.new do |opts|
774
- opts.banner = subcommand_usage("[name]")
790
+ opts.banner = subcommand_usage("[role] [group] [access]")
775
791
  opts.on( '-g', '--group GROUP', "Group name or id" ) do |val|
776
792
  group_name = val
777
793
  end
778
794
  opts.on( nil, '--all', "Update all groups at once." ) do
779
795
  do_all = true
780
796
  end
781
- opts.on( '--access VALUE', String, "Access value [full|read|none]" ) do |val|
797
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
782
798
  access_value = val
783
799
  end
784
800
  build_common_options(opts, options, [:json, :dry_run, :remote])
785
801
  opts.footer = "Update role access for a group or all groups.\n" +
786
- "[name] is required. This is the name or id of a role.\n" +
802
+ "[role] is required. This is the name or id of a role.\n" +
787
803
  "--group or --all is required. This is the name or id of a group.\n" +
788
- "--access is required. This is the new access value."
804
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
789
805
  end
790
806
  optparse.parse!(args)
791
- if args.count < 1
792
- puts optparse
793
- return 1
794
- end
795
- name = args[0]
796
- # support old usage: [name] [group] [access]
797
- group_name ||= args[1]
798
- access_value ||= args[2]
799
807
 
800
- if (!group_name && !do_all) || !access_value
801
- puts optparse
802
- return 1
808
+ # usage: update-group-access [role] [access] --all
809
+ # update-group-access [role] [group] [access]
810
+ name = args[0]
811
+ if do_all
812
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
813
+ access_value = args[1] if args[1]
814
+ else
815
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
816
+ group_id = args[1] if args[1]
817
+ access_value = args[2] if args[2]
818
+ end
819
+ if !group_id && !do_all
820
+ raise_command_error("missing required argument: [group] or --all", optparse)
821
+ end
822
+ if !access_value
823
+ raise_command_error("missing required argument: [access]", optparse)
803
824
  end
804
-
805
825
  access_value = access_value.to_s.downcase
806
-
807
- if !['full', 'read', 'none'].include?(access_value)
826
+ if !allowed_access_values.include?(access_value)
827
+ raise_command_error("invalid access value: #{access_value}", optparse)
808
828
  puts optparse
809
829
  return 1
810
830
  end
@@ -915,6 +935,7 @@ EOT
915
935
  cloud_name = nil
916
936
  access_value = nil
917
937
  do_all = false
938
+ allowed_access_values = ['full', 'read', 'none']
918
939
  optparse = Morpheus::Cli::OptionParser.new do |opts|
919
940
  opts.banner = subcommand_usage("[name]")
920
941
  opts.on( '-c', '--cloud CLOUD', "Cloud name or id" ) do |val|
@@ -924,7 +945,7 @@ EOT
924
945
  opts.on( nil, '--all', "Update all clouds at once." ) do
925
946
  do_all = true
926
947
  end
927
- opts.on( '--access VALUE', String, "Access value [full|read|none]" ) do |val|
948
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
928
949
  access_value = val
929
950
  end
930
951
  opts.on( '-g', '--group GROUP', "Group to find cloud in" ) do |val|
@@ -932,32 +953,34 @@ EOT
932
953
  end
933
954
  build_common_options(opts, options, [:json, :dry_run, :remote])
934
955
  opts.footer = "Update role access for a cloud or all clouds.\n" +
935
- "[name] is required. This is the name or id of a role.\n" +
956
+ "[role] is required. This is the name or id of a role.\n" +
936
957
  "--cloud or --all is required. This is the name or id of a cloud.\n" +
937
- "--access is required. This is the new access value."
958
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
938
959
  end
939
960
  optparse.parse!(args)
940
961
 
941
- if args.count < 1
942
- puts optparse
943
- return 1
944
- end
962
+ # usage: update-cloud-access [role] [access] --all
963
+ # update-cloud-access [role] [cloud] [access]
945
964
  name = args[0]
946
- # support old usage: [name] [cloud] [access]
947
- cloud_name ||= args[1]
948
- access_value ||= args[2]
949
-
950
- if (!cloud_name && !do_all) || !access_value
951
- puts optparse
952
- return 1
965
+ if do_all
966
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
967
+ access_value = args[1] if args[1]
968
+ else
969
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
970
+ cloud_id = args[1] if args[1]
971
+ access_value = args[2] if args[2]
972
+ end
973
+ if !cloud_id && !do_all
974
+ raise_command_error("missing required argument: [cloud] or --all", optparse)
975
+ end
976
+ if !access_value
977
+ raise_command_error("missing required argument: [access]", optparse)
953
978
  end
954
- puts "cloud_name is : #{cloud_name}"
955
- puts "access_value is : #{access_value}"
956
979
  access_value = access_value.to_s.downcase
957
-
958
- if !['full', 'none'].include?(access_value)
980
+ if !allowed_access_values.include?(access_value)
981
+ raise_command_error("invalid access value: #{access_value}", optparse)
959
982
  puts optparse
960
- exit 1
983
+ return 1
961
984
  end
962
985
 
963
986
  connect(options)
@@ -1025,10 +1048,10 @@ EOT
1025
1048
  end
1026
1049
 
1027
1050
  def update_global_instance_type_access(args)
1028
- usage = "Usage: morpheus roles update-global-instance-type-access [name] [full|custom|none]"
1051
+ usage = "Usage: morpheus roles update-global-instance-type-access [role] [full|custom|none]"
1029
1052
  options = {}
1030
1053
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1031
- opts.banner = subcommand_usage("[name] [full|custom|none]")
1054
+ opts.banner = subcommand_usage("[role] [full|custom|none]")
1032
1055
  build_common_options(opts, options, [:json, :dry_run, :remote])
1033
1056
  end
1034
1057
  optparse.parse!(args)
@@ -1077,22 +1100,23 @@ EOT
1077
1100
  instance_type_name = nil
1078
1101
  access_value = nil
1079
1102
  do_all = false
1103
+ allowed_access_values = ['full', 'none']
1080
1104
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1081
- opts.banner = subcommand_usage("[name]")
1105
+ opts.banner = subcommand_usage("[role] [type] [access]")
1082
1106
  opts.on( '--instance-type INSTANCE_TYPE', String, "Instance Type name" ) do |val|
1083
1107
  instance_type_name = val
1084
1108
  end
1085
1109
  opts.on( nil, '--all', "Update all instance types at once." ) do
1086
1110
  do_all = true
1087
1111
  end
1088
- opts.on( '--access VALUE', String, "Access value [full|read|none]" ) do |val|
1112
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
1089
1113
  access_value = val
1090
1114
  end
1091
1115
  build_common_options(opts, options, [:json, :dry_run, :remote])
1092
1116
  opts.footer = "Update role access for an instance type or all instance types.\n" +
1093
- "[name] is required. This is the name or id of a role.\n" +
1117
+ "[role] is required. This is the name or id of a role.\n" +
1094
1118
  "--instance-type or --all is required. This is the name of an instance type.\n" +
1095
- "--access is required. This is the new access value."
1119
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1096
1120
  end
1097
1121
  optparse.parse!(args)
1098
1122
 
@@ -1101,7 +1125,7 @@ EOT
1101
1125
  return 1
1102
1126
  end
1103
1127
  name = args[0]
1104
- # support old usage: [name] [instance-type] [access]
1128
+ # support old usage: [role] [instance-type] [access]
1105
1129
  instance_type_name ||= args[1]
1106
1130
  access_value ||= args[2]
1107
1131
 
@@ -1170,10 +1194,10 @@ EOT
1170
1194
  end
1171
1195
 
1172
1196
  def update_global_blueprint_access(args)
1173
- usage = "Usage: morpheus roles update-global-blueprint-access [name] [full|custom|none]"
1197
+ usage = "Usage: morpheus roles update-global-blueprint-access [role] [full|custom|none]"
1174
1198
  options = {}
1175
1199
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1176
- opts.banner = subcommand_usage("[name] [full|custom|none]")
1200
+ opts.banner = subcommand_usage("[role] [full|custom|none]")
1177
1201
  build_common_options(opts, options, [:json, :dry_run, :remote])
1178
1202
  end
1179
1203
  optparse.parse!(args)
@@ -1222,42 +1246,46 @@ EOT
1222
1246
  blueprint_id = nil
1223
1247
  access_value = nil
1224
1248
  do_all = false
1249
+ allowed_access_values = ['full', 'none']
1225
1250
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1226
- opts.banner = subcommand_usage("[name]")
1251
+ opts.banner = subcommand_usage("[role] [blueprint] [access]")
1227
1252
  opts.on( '--blueprint ID', String, "Blueprint ID or Name" ) do |val|
1228
1253
  blueprint_id = val
1229
1254
  end
1230
1255
  opts.on( nil, '--all', "Update all blueprints at once." ) do
1231
1256
  do_all = true
1232
1257
  end
1233
- opts.on( '--access VALUE', String, "Access value [full|read|none]" ) do |val|
1258
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
1234
1259
  access_value = val
1235
1260
  end
1236
1261
  build_common_options(opts, options, [:json, :dry_run, :remote])
1237
1262
  opts.footer = "Update role access for an blueprint or all blueprints.\n" +
1238
- "[name] is required. This is the name or id of a role.\n" +
1263
+ "[role] is required. This is the name or id of a role.\n" +
1239
1264
  "--blueprint or --all is required. This is the name or id of a blueprint.\n" +
1240
- "--access is required. This is the new access value."
1265
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1241
1266
  end
1242
1267
  optparse.parse!(args)
1243
1268
 
1244
- if args.count < 1
1245
- puts optparse
1246
- return 1
1247
- end
1269
+ # usage: update-blueprint-access [role] [access] --all
1270
+ # update-blueprint-access [role] [blueprint] [access]
1248
1271
  name = args[0]
1249
- # support old usage: [name] [blueprint] [access]
1250
- blueprint_id ||= args[1]
1251
- access_value ||= args[2]
1252
-
1253
- if (!blueprint_id && !do_all) || !access_value
1254
- puts_error optparse
1255
- return 1
1272
+ if do_all
1273
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
1274
+ access_value = args[1] if args[1]
1275
+ else
1276
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
1277
+ blueprint_id = args[1] if args[1]
1278
+ access_value = args[2] if args[2]
1279
+ end
1280
+ if !blueprint_id && !do_all
1281
+ raise_command_error("missing required argument: [blueprint] or --all", optparse)
1282
+ end
1283
+ if !access_value
1284
+ raise_command_error("missing required argument: [access]", optparse)
1256
1285
  end
1257
-
1258
1286
  access_value = access_value.to_s.downcase
1259
-
1260
- if !['full', 'none'].include?(access_value)
1287
+ if !allowed_access_values.include?(access_value)
1288
+ raise_command_error("invalid access value: #{access_value}", optparse)
1261
1289
  puts optparse
1262
1290
  return 1
1263
1291
  end
@@ -1327,10 +1355,10 @@ EOT
1327
1355
  end
1328
1356
 
1329
1357
  def update_global_catalog_item_type_access(args)
1330
- usage = "Usage: morpheus roles update-global-catalog-item-type-access [name] [full|custom|none]"
1358
+ usage = "Usage: morpheus roles update-global-catalog-item-type-access [role] [full|custom|none]"
1331
1359
  options = {}
1332
1360
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1333
- opts.banner = subcommand_usage("[name] [full|custom|none]")
1361
+ opts.banner = subcommand_usage("[role] [full|custom|none]")
1334
1362
  build_common_options(opts, options, [:json, :dry_run, :remote])
1335
1363
  end
1336
1364
  optparse.parse!(args)
@@ -1379,42 +1407,46 @@ EOT
1379
1407
  catalog_item_type_id = nil
1380
1408
  access_value = nil
1381
1409
  do_all = false
1410
+ allowed_access_values = ['full', 'none']
1382
1411
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1383
- opts.banner = subcommand_usage("[name]")
1412
+ opts.banner = subcommand_usage("[role] [catalog-item-type] [access]")
1384
1413
  opts.on( '--catalog-item-type ID', String, "Catalog Item Type ID or Name" ) do |val|
1385
1414
  catalog_item_type_id = val
1386
1415
  end
1387
1416
  opts.on( nil, '--all', "Update all catalog item types at once." ) do
1388
1417
  do_all = true
1389
1418
  end
1390
- opts.on( '--access VALUE', String, "Access value [full|none]" ) do |val|
1419
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
1391
1420
  access_value = val
1392
1421
  end
1393
1422
  build_common_options(opts, options, [:json, :dry_run, :remote])
1394
1423
  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" +
1424
+ "[role] is required. This is the name or id of a role.\n" +
1396
1425
  "--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."
1426
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1398
1427
  end
1399
1428
  optparse.parse!(args)
1400
1429
 
1401
- if args.count < 1
1402
- puts optparse
1403
- return 1
1404
- end
1430
+ # usage: update-catalog_item_type-access [role] [access] --all
1431
+ # update-catalog_item_type-access [role] [catalog-item-type] [access]
1405
1432
  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
1433
+ if do_all
1434
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
1435
+ access_value = args[1] if args[1]
1436
+ else
1437
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
1438
+ catalog_item_type_id = args[1] if args[1]
1439
+ access_value = args[2] if args[2]
1440
+ end
1441
+ if !catalog_item_type_id && !do_all
1442
+ raise_command_error("missing required argument: [catalog-item-type] or --all", optparse)
1443
+ end
1444
+ if !access_value
1445
+ raise_command_error("missing required argument: [access]", optparse)
1413
1446
  end
1414
-
1415
1447
  access_value = access_value.to_s.downcase
1416
-
1417
- if !['full', 'none'].include?(access_value)
1448
+ if !allowed_access_values.include?(access_value)
1449
+ raise_command_error("invalid access value: #{access_value}", optparse)
1418
1450
  puts optparse
1419
1451
  return 1
1420
1452
  end
@@ -1484,44 +1516,49 @@ EOT
1484
1516
  def update_persona_access(args)
1485
1517
  options = {}
1486
1518
  persona_id = nil
1519
+ name = nil
1487
1520
  access_value = nil
1488
1521
  do_all = false
1522
+ allowed_access_values = ['full', 'none']
1489
1523
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1490
- opts.banner = subcommand_usage("[name] [serviceCatalog|standard]")
1524
+ opts.banner = subcommand_usage("[role] [persona] [access]")
1491
1525
  opts.on( '--persona CODE', String, "Persona Code" ) do |val|
1492
1526
  persona_id = val
1493
1527
  end
1494
1528
  opts.on( nil, '--all', "Update all personas at once." ) do
1495
1529
  do_all = true
1496
1530
  end
1497
- opts.on( '--access VALUE', String, "Access value [full|none]" ) do |val|
1531
+ opts.on( '--access VALUE', String, "Access value [#{allowed_access_values.join('|')}]" ) do |val|
1498
1532
  access_value = val
1499
1533
  end
1500
1534
  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."
1535
+ opts.footer = "Update role access for a persona or all personas.\n" +
1536
+ "[role] is required. This is the name or id of a role.\n" +
1537
+ "--persona or --all is required. This is the code of a persona. Service Catalog or Standard\n" +
1538
+ "--access is required. This is the new access value. #{anded_list(allowed_access_values)}"
1505
1539
  end
1506
1540
  optparse.parse!(args)
1507
1541
 
1508
- if args.count < 1
1509
- puts optparse
1510
- return 1
1511
- end
1542
+ # usage: update-persona-access [role] [access] --all
1543
+ # update-persona-access [role] [persona] [access]
1512
1544
  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
1545
+ if do_all
1546
+ verify_args!(args:args, optparse:optparse, min:1, max:2)
1547
+ access_value = args[1] if args[1]
1548
+ else
1549
+ verify_args!(args:args, optparse:optparse, min:1, max:3)
1550
+ persona_id = args[1] if args[1]
1551
+ access_value = args[2] if args[2]
1552
+ end
1553
+ if !persona_id && !do_all
1554
+ raise_command_error("missing required argument: [persona] or --all", optparse)
1555
+ end
1556
+ if !access_value
1557
+ raise_command_error("missing required argument: [access]", optparse)
1520
1558
  end
1521
-
1522
1559
  access_value = access_value.to_s.downcase
1523
-
1524
- if !['full', 'none'].include?(access_value)
1560
+ if !allowed_access_values.include?(access_value)
1561
+ raise_command_error("invalid access value: #{access_value}", optparse)
1525
1562
  puts optparse
1526
1563
  return 1
1527
1564
  end
@@ -1573,12 +1610,13 @@ EOT
1573
1610
 
1574
1611
  def add_role_option_types
1575
1612
  [
1576
- {'fieldName' => 'authority', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
1577
- {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
1578
- {'fieldName' => 'roleType', 'fieldLabel' => 'Role Type', 'type' => 'select', 'selectOptions' => [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}], 'defaultValue' => 'user', 'displayOrder' => 3},
1579
- {'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text', 'displayOrder' => 4},
1580
- {'fieldName' => 'multitenant', 'fieldLabel' => 'Multitenant', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'A Multitenant role is automatically copied into all existing subaccounts as well as placed into a subaccount when created. Useful for providing a set of predefined roles a Customer can use', 'displayOrder' => 5},
1581
- {'fieldName' => 'multitenantLocked', 'fieldLabel' => 'Multitenant Locked', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'Prevents subtenants from branching off this role/modifying it. ', 'displayOrder' => 6}
1613
+ {'fieldName' => 'authority', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
1614
+ {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text'},
1615
+ {'fieldName' => 'roleType', 'fieldLabel' => 'Role Type', 'type' => 'select', 'selectOptions' => [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}], 'defaultValue' => 'user'},
1616
+ {'fieldName' => 'baseRole', 'fieldLabel' => 'Copy From Role', 'type' => 'text'},
1617
+ {'fieldName' => 'multitenant', 'fieldLabel' => 'Multitenant', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'A Multitenant role is automatically copied into all existing subaccounts as well as placed into a subaccount when created. Useful for providing a set of predefined roles a Customer can use'},
1618
+ {'fieldName' => 'multitenantLocked', 'fieldLabel' => 'Multitenant Locked', 'type' => 'checkbox', 'defaultValue' => 'off', 'description' => 'Prevents subtenants from branching off this role/modifying it. '},
1619
+ {'fieldName' => 'defaultPersona', 'fieldLabel' => 'Default Persona', 'type' => 'select', 'selectOptions' => [{'name'=>'Service Catalog','value'=>'serviceCatalog'},{'name'=>'Standard','value'=>'standard'}], 'description' => 'Default Persona'}
1582
1620
  ]
1583
1621
  end
1584
1622