morpheus-cli 4.2.14 → 4.2.19

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +8 -6
  4. data/lib/morpheus/api/api_client.rb +32 -14
  5. data/lib/morpheus/api/auth_interface.rb +4 -2
  6. data/lib/morpheus/api/backup_jobs_interface.rb +9 -0
  7. data/lib/morpheus/api/backups_interface.rb +16 -0
  8. data/lib/morpheus/api/deploy_interface.rb +25 -56
  9. data/lib/morpheus/api/deployments_interface.rb +44 -55
  10. data/lib/morpheus/api/doc_interface.rb +57 -0
  11. data/lib/morpheus/api/instances_interface.rb +5 -0
  12. data/lib/morpheus/api/rest_interface.rb +40 -0
  13. data/lib/morpheus/api/user_sources_interface.rb +0 -15
  14. data/lib/morpheus/api/users_interface.rb +2 -3
  15. data/lib/morpheus/benchmarking.rb +2 -2
  16. data/lib/morpheus/cli.rb +4 -1
  17. data/lib/morpheus/cli/access_token_command.rb +27 -10
  18. data/lib/morpheus/cli/apps.rb +21 -15
  19. data/lib/morpheus/cli/backup_jobs_command.rb +276 -0
  20. data/lib/morpheus/cli/backups_command.rb +271 -0
  21. data/lib/morpheus/cli/blueprints_command.rb +27 -61
  22. data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
  23. data/lib/morpheus/cli/cli_command.rb +183 -45
  24. data/lib/morpheus/cli/cli_registry.rb +3 -0
  25. data/lib/morpheus/cli/clouds.rb +7 -10
  26. data/lib/morpheus/cli/clusters.rb +0 -18
  27. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +23 -20
  28. data/lib/morpheus/cli/commands/standard/man_command.rb +1 -1
  29. data/lib/morpheus/cli/credentials.rb +13 -9
  30. data/lib/morpheus/cli/deploy.rb +374 -0
  31. data/lib/morpheus/cli/deployments.rb +521 -197
  32. data/lib/morpheus/cli/deploys.rb +271 -126
  33. data/lib/morpheus/cli/doc.rb +182 -0
  34. data/lib/morpheus/cli/error_handler.rb +23 -8
  35. data/lib/morpheus/cli/errors.rb +3 -2
  36. data/lib/morpheus/cli/image_builder_command.rb +2 -2
  37. data/lib/morpheus/cli/instances.rb +136 -17
  38. data/lib/morpheus/cli/invoices_command.rb +339 -225
  39. data/lib/morpheus/cli/jobs_command.rb +2 -2
  40. data/lib/morpheus/cli/library_layouts_command.rb +1 -1
  41. data/lib/morpheus/cli/library_option_lists_command.rb +61 -125
  42. data/lib/morpheus/cli/library_option_types_command.rb +32 -37
  43. data/lib/morpheus/cli/login.rb +9 -3
  44. data/lib/morpheus/cli/mixins/accounts_helper.rb +158 -100
  45. data/lib/morpheus/cli/mixins/backups_helper.rb +115 -0
  46. data/lib/morpheus/cli/mixins/deployments_helper.rb +135 -0
  47. data/lib/morpheus/cli/mixins/library_helper.rb +32 -0
  48. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  49. data/lib/morpheus/cli/mixins/print_helper.rb +149 -84
  50. data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -2
  51. data/lib/morpheus/cli/mixins/whoami_helper.rb +19 -6
  52. data/lib/morpheus/cli/network_routers_command.rb +1 -1
  53. data/lib/morpheus/cli/option_parser.rb +48 -5
  54. data/lib/morpheus/cli/option_types.rb +46 -10
  55. data/lib/morpheus/cli/price_sets_command.rb +1 -1
  56. data/lib/morpheus/cli/projects_command.rb +7 -7
  57. data/lib/morpheus/cli/remote.rb +3 -2
  58. data/lib/morpheus/cli/roles.rb +49 -92
  59. data/lib/morpheus/cli/security_groups.rb +7 -1
  60. data/lib/morpheus/cli/service_plans_command.rb +10 -10
  61. data/lib/morpheus/cli/setup.rb +1 -1
  62. data/lib/morpheus/cli/shell.rb +7 -6
  63. data/lib/morpheus/cli/subnets_command.rb +1 -1
  64. data/lib/morpheus/cli/tasks.rb +24 -10
  65. data/lib/morpheus/cli/tenants_command.rb +133 -163
  66. data/lib/morpheus/cli/user_groups_command.rb +20 -65
  67. data/lib/morpheus/cli/user_settings_command.rb +115 -13
  68. data/lib/morpheus/cli/user_sources_command.rb +57 -24
  69. data/lib/morpheus/cli/users.rb +210 -186
  70. data/lib/morpheus/cli/version.rb +1 -1
  71. data/lib/morpheus/cli/whitelabel_settings_command.rb +29 -5
  72. data/lib/morpheus/cli/whoami.rb +113 -6
  73. data/lib/morpheus/cli/workflows.rb +11 -8
  74. data/lib/morpheus/ext/hash.rb +21 -0
  75. data/lib/morpheus/formatters.rb +7 -19
  76. data/lib/morpheus/terminal.rb +1 -0
  77. metadata +12 -3
  78. data/lib/morpheus/cli/auth_command.rb +0 -105
@@ -70,7 +70,7 @@ module Morpheus::Cli::ProvisioningHelper
70
70
 
71
71
  def get_available_clouds(group_id, refresh=false)
72
72
  if !group_id
73
- option_results = options_interface.options_for_source('clouds', {})
73
+ option_results = options_interface.options_for_source('clouds', {'default' => 'false'})
74
74
  return option_results['data'].collect {|it|
75
75
  {"id" => it["value"], "name" => it["name"], "value" => it["value"], "zoneTypeId" => it["zoneTypeId"]}
76
76
  }
@@ -244,7 +244,7 @@ module Morpheus::Cli::ProvisioningHelper
244
244
  end
245
245
 
246
246
  def find_instance_by_name(name)
247
- json_results = instances_interface.get({name: name.to_s})
247
+ json_results = instances_interface.list({name: name.to_s})
248
248
  if json_results['instances'].empty?
249
249
  print_red_alert "Instance not found by name #{name}"
250
250
  exit 1
@@ -1,18 +1,31 @@
1
1
  require 'morpheus/cli/mixins/print_helper'
2
2
 
3
3
  # Mixin for Morpheus::Cli command classes
4
- # Provides common methods for fetching and printing accounts, roles, and users.
5
- # The including class must establish @accounts_interface, @roles_interface, @users_interface
4
+ # Provides common methods for fetching and printing whoami information
6
5
  module Morpheus::Cli::WhoamiHelper
7
6
 
8
7
  def self.included(klass)
9
8
  klass.send :include, Morpheus::Cli::PrintHelper
10
9
  end
11
10
 
12
- def load_whoami()
13
- whoami_interface = @whoami_interface || @api_client.whoami
14
- whoami_response = whoami_interface.get()
15
- # whoami_response = @whoami_interface.get()
11
+ def load_whoami(refresh=false)
12
+ appliance = @remote_appliance # from establish_connection()
13
+ if appliance.nil?
14
+ print_red_alert "No current appliance. See `remote use`."
15
+ exit 1
16
+ end
17
+ # fetch from cache first
18
+ whoami_response = nil
19
+ cached_response = ::Morpheus::Cli::Whoami.load_whoami(appliance[:name], appliance[:username], refresh)
20
+ if cached_response
21
+ whoami_response = cached_response
22
+ else
23
+ whoami_interface = @whoami_interface || @api_client.whoami
24
+ whoami_response = whoami_interface.get()
25
+ # save the result to the cache
26
+ ::Morpheus::Cli::Whoami.save_whoami(appliance[:name], appliance[:username], whoami_response)
27
+ end
28
+
16
29
  @current_user = whoami_response["user"]
17
30
  if @current_user.empty?
18
31
  print_red_alert "Unauthenticated. Please login."
@@ -1040,7 +1040,7 @@ class Morpheus::Cli::NetworkRoutersCommand
1040
1040
 
1041
1041
  begin
1042
1042
  if !is_master_account
1043
- print_red_alert "Permissions only available for master account"
1043
+ print_red_alert "Permissions only available for master tenant"
1044
1044
  return 1
1045
1045
  end
1046
1046
 
@@ -4,7 +4,11 @@ module Morpheus
4
4
  module Cli
5
5
 
6
6
  # an enhanced OptionParser
7
- # not used yet, maybe ever =o
7
+ # Modifications include
8
+ # * footer property to compliment banner with footer="Get details about a thing by ID."
9
+ # * hidden options with add_hidden_option "--not-in-help"
10
+ # * errors raised from parse! will have a reference to the parser itself.
11
+ # this is useful so you can you print the banner (usage) message in your error handling
8
12
  class Morpheus::Cli::OptionParser < OptionParser
9
13
 
10
14
  attr_accessor :footer
@@ -18,7 +22,7 @@ module Morpheus
18
22
  full_help_message
19
23
  end
20
24
 
21
- def full_help_message
25
+ def full_help_message(opts={})
22
26
  out = ""
23
27
  #out << original_to_s
24
28
  if banner
@@ -40,8 +44,15 @@ module Morpheus
40
44
  opt_description.to_s.strip.start_with?("--#{hidden_switch} ")
41
45
  end
42
46
  }
43
- if !is_hidden
44
- out << opt_description
47
+ if is_hidden
48
+ if opts[:show_hidden_options]
49
+ # out << opt_description + " (hidden)"
50
+ out << opt_description
51
+ else
52
+ # hidden
53
+ end
54
+ else
55
+ out << opt_description
45
56
  end
46
57
  end
47
58
  end
@@ -66,7 +77,39 @@ module Morpheus
66
77
  @hidden_options
67
78
  end
68
79
 
69
- end
80
+ # this needs mods too, but we dont use it...
81
+ # def parse
82
+ # end
70
83
 
84
+ def parse!(*args)
85
+ # it is actually # def parse(argv = default_argv, into: nil)
86
+ argv = [args].flatten() # args[0].flatten
87
+ #help_wanted = argv.find {|arg| arg == "--help" || arg == "-h" }
88
+ help_wanted = (argv.last == "--help" || argv.last == "-h") ? argv.last : nil
89
+ begin
90
+ return super(*args)
91
+ rescue OptionParser::ParseError => e
92
+ # last arg is --help
93
+ # maybe they just got the Try --help message and its on the end
94
+ # so strip all option arguments to avoid OptionParser::InvalidOption, etc.
95
+ # this is not ideal, it means you cannot pass these strings as the last argument to your command.
96
+ if help_wanted
97
+ argv = argv.reject {|arg| arg =~ /^\-+/ }
98
+ argv << help_wanted
99
+ return super(argv)
100
+ else
101
+ e.optparse = self
102
+ raise e
103
+ end
104
+
105
+ end
106
+ end
107
+ end
71
108
  end
72
109
  end
110
+
111
+ # ParseError is overridden to set parser reference.
112
+ # todo: dont monkey patch like this
113
+ class OptionParser::ParseError
114
+ attr_accessor :optparse
115
+ end
@@ -47,7 +47,9 @@ module Morpheus
47
47
  end
48
48
  end
49
49
  # puts "Options Prompt #{options}"
50
- option_types.sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |option_type|
50
+ # only sort if displayOrder is set
51
+ sorted_option_types = (option_types[0] && option_types[0]['displayOrder']) ? option_types.sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i } : option_types
52
+ sorted_option_types.each do |option_type|
51
53
  context_map = results
52
54
  value = nil
53
55
  value_found=false
@@ -71,17 +73,26 @@ module Morpheus
71
73
 
72
74
  # respect optionType.dependsOnCode
73
75
  if option_type['dependsOnCode'] && option_type['dependsOnCode'] != ""
74
- # optionTypes can have this setting in the format code=value or code:value
76
+ # support formats code=value or code:value OR code:(value|value2|value3)
75
77
  parts = option_type['dependsOnCode'].include?("=") ? option_type['dependsOnCode'].split("=") : option_type['dependsOnCode'].split(":")
76
78
  depends_on_code = parts[0]
77
- depends_on_value = parts[1]
79
+ depends_on_value = parts[1].to_s.strip
80
+ depends_on_values = []
81
+ if depends_on_value.size > 0
82
+ # strip parenthesis
83
+ if depends_on_value[0] && depends_on_value[0].chr == "("
84
+ depends_on_value = depends_on_value[1..-1]
85
+ end
86
+ depends_on_value.chomp(")")
87
+ depends_on_values = depends_on_value.split("|").collect { |it| it.strip }
88
+ end
78
89
  depends_on_option_type = option_types.find {|it| it["code"] == depends_on_code }
79
90
  # could not find the dependent option type, proceed and prompt
80
91
  if !depends_on_option_type.nil?
81
92
  # dependent option type has a different value
82
93
  depends_on_field_key = depends_on_option_type['fieldContext'] ? "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldName']}"
83
94
  found_dep_value = get_object_value(results, depends_on_field_key) || get_object_value(options, depends_on_field_key)
84
- if depends_on_value && depends_on_value != found_dep_value
95
+ if depends_on_values.size > 0 && !depends_on_values.include?(found_dep_value)
85
96
  next
86
97
  end
87
98
  end
@@ -311,7 +322,7 @@ module Morpheus
311
322
  elsif option_type['optionSource']
312
323
  # calculate from inline lambda
313
324
  if option_type['optionSource'].is_a?(Proc)
314
- select_options = option_type['optionSource'].call()
325
+ select_options = option_type['optionSource'].call(api_client, grails_params(api_params || {}))
315
326
  elsif option_type['optionSource'] == 'list'
316
327
  # /api/options/list is a special action for custom OptionTypeLists, just need to pass the optionTypeId parameter
317
328
  select_options = load_source_options(option_type['optionSource'], api_client, {'optionTypeId' => option_type['id']})
@@ -622,14 +633,28 @@ module Morpheus
622
633
  if source_type == "local"
623
634
  # prompt for content
624
635
  if file_params['content'].nil?
625
- file_params['content'] = multiline_prompt({'fieldContext' => full_field_key, 'fieldName' => 'content', 'type' => 'code-editor', 'fieldLabel' => 'Content', 'required' => true})
636
+ if options[:no_prompt]
637
+ print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
638
+ print Term::ANSIColor.red, " * Content [-O #{full_field_key}.content=] - File Content\n", Term::ANSIColor.reset
639
+ print "\n"
640
+ exit 1
641
+ else
642
+ file_params['content'] = multiline_prompt({'fieldContext' => full_field_key, 'fieldName' => 'content', 'type' => 'code-editor', 'fieldLabel' => 'Content', 'required' => true})
643
+ end
626
644
  end
627
645
  elsif source_type == "url"
628
646
  if file_params['url']
629
647
  file_params['contentPath'] = file_params.delete('url')
630
648
  end
631
649
  if file_params['contentPath'].nil?
632
- file_params['contentPath'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'url', 'fieldLabel' => 'URL', 'type' => 'text', 'required' => true})
650
+ if options[:no_prompt]
651
+ print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
652
+ print Term::ANSIColor.red, " * URL [-O #{full_field_key}.url=] - Path of file in the repository\n", Term::ANSIColor.reset
653
+ print "\n"
654
+ exit 1
655
+ else
656
+ file_params['contentPath'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'url', 'fieldLabel' => 'URL', 'type' => 'text', 'required' => true})
657
+ end
633
658
  end
634
659
  elsif source_type == "repository"
635
660
  if file_params['repository'].nil?
@@ -637,10 +662,21 @@ module Morpheus
637
662
  file_params['repository'] = {'id' => repository_id}
638
663
  end
639
664
  if file_params['contentPath'].nil?
640
- file_params['contentPath'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'path', 'fieldLabel' => 'File Path', 'type' => 'text', 'required' => true})
665
+ if options[:no_prompt]
666
+ print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
667
+ print Term::ANSIColor.red, " * File Path [-O #{full_field_key}.path=] - Path of file in the repository\n", Term::ANSIColor.reset
668
+ print "\n"
669
+ exit 1
670
+ else
671
+ file_params['contentPath'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'path', 'fieldLabel' => 'File Path', 'type' => 'text', 'required' => true})
672
+ end
641
673
  end
642
- if file_params['contentRef'].nil?
643
- file_params['contentRef'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'ref', 'fieldLabel' => 'Version Ref', 'type' => 'text'})
674
+ if !file_params.key?('contentRef')
675
+ if options[:no_prompt]
676
+ # pass
677
+ else
678
+ file_params['contentRef'] = generic_prompt({'fieldContext' => full_field_key, 'fieldName' => 'ref', 'fieldLabel' => 'Version Ref', 'type' => 'text'})
679
+ end
644
680
  end
645
681
  end
646
682
  return file_params
@@ -461,7 +461,7 @@ class Morpheus::Cli::PriceSetsCommand
461
461
  private
462
462
 
463
463
  def currency_sym(currency)
464
- Money::Currency.new((currency || 'usd').to_sym).symbol
464
+ Money::Currency.new((currency.to_s != '' ? currency : 'usd').to_sym).symbol
465
465
  end
466
466
 
467
467
  def price_prefix(price)
@@ -102,7 +102,7 @@ EOT
102
102
  options = {}
103
103
  optparse = Morpheus::Cli::OptionParser.new do |opts|
104
104
  opts.banner = subcommand_usage("[project]")
105
- build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
105
+ build_standard_get_options(opts, options, [:find_by_name])
106
106
  opts.footer = <<-EOT
107
107
  Get details about a project.
108
108
  [project] is required. This is the name or id of a project.
@@ -127,8 +127,8 @@ EOT
127
127
  end
128
128
  return
129
129
  end
130
- project = find_project_by_name_or_id(id)
131
- exit 1 if project.nil?
130
+ project = options[:find_by_name] ? find_project_by_name(id) : find_project_by_name_or_id(id)
131
+ return 1, "project not found by '#{id}'" if project.nil?
132
132
  # refetch it by id
133
133
  json_response = {'project' => project}
134
134
  unless id.to_s =~ /\A\d{1,}\Z/
@@ -332,7 +332,7 @@ EOT
332
332
  opts.on('--remove-resources LIST', Array, "Remove Resources, comma separated list of resource names or IDs to remove.") do |list|
333
333
  remove_resource_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
334
334
  end
335
- build_standard_update_options(opts, options)
335
+ build_standard_update_options(opts, options, [:find_by_name])
336
336
  opts.footer = <<-EOT
337
337
  Update a project.
338
338
  [project] is required. This is the name or id of a project.
@@ -342,7 +342,7 @@ EOT
342
342
  verify_args!(args:args, optparse:optparse, count:1)
343
343
  connect(options)
344
344
  exit_code, err = 0, nil
345
- project = find_project_by_name_or_id(args[0])
345
+ project = options[:find_by_name] ? find_project_by_name(args[0]) : find_project_by_name_or_id(args[0])
346
346
  return 1, "project not found by '#{args[0]}'" if project.nil?
347
347
  # construct payload
348
348
  if options[:payload]
@@ -433,7 +433,7 @@ EOT
433
433
  options = {}
434
434
  optparse = Morpheus::Cli::OptionParser.new do |opts|
435
435
  opts.banner = subcommand_usage("[project]")
436
- build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
436
+ build_standard_remove_options(opts, options, [:find_by_name])
437
437
  # opts.on( '-f', '--force', "Force Delete" ) do
438
438
  # params[:force] = true
439
439
  # end
@@ -446,7 +446,7 @@ EOT
446
446
  verify_args!(args:args, optparse:optparse, count:1)
447
447
  connect(options)
448
448
  exit_code, err = 0, nil
449
- project = find_project_by_name_or_id(args[0])
449
+ project = options[:find_by_name] ? find_project_by_name(args[0]) : find_project_by_name_or_id(args[0])
450
450
  return 1, "project not found by '#{args[0]}'" if project.nil?
451
451
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the project #{project['name']}?")
452
452
  return 9, "aborted command"
@@ -44,7 +44,7 @@ class Morpheus::Cli::Remote
44
44
  current_only = false
45
45
  do_check = false
46
46
  optparse = Morpheus::Cli::OptionParser.new do|opts|
47
- opts.banner = subcommand_usage()
47
+ opts.banner = subcommand_usage("[search]")
48
48
  opts.on("-a",'--all', "Show all the appliance activity details") do
49
49
  show_all_activity = true
50
50
  options[:wrap] = true
@@ -61,8 +61,9 @@ List the configured remote appliances.
61
61
  EOT
62
62
  end
63
63
  optparse.parse!(args)
64
+ # verify_args!(args:args, optparse:optparse, count:0)
64
65
  if args.count > 0
65
- raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
66
+ options[:phrase] = args.join(" ")
66
67
  end
67
68
  #connect(options)
68
69
  params.merge!(parse_list_options(options))
@@ -12,6 +12,7 @@ class Morpheus::Cli::Roles
12
12
  include Morpheus::Cli::CliCommand
13
13
  include Morpheus::Cli::AccountsHelper
14
14
  include Morpheus::Cli::ProvisioningHelper
15
+ include Morpheus::Cli::WhoamiHelper
15
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
17
  alias_subcommand :details, :get
17
18
  set_default_subcommand :list
@@ -37,36 +38,28 @@ class Morpheus::Cli::Roles
37
38
  def list(args)
38
39
  options = {}
39
40
  optparse = Morpheus::Cli::OptionParser.new do |opts|
40
- opts.banner = subcommand_usage()
41
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
41
+ opts.banner = subcommand_usage("[search phrase]")
42
+ build_standard_list_options(opts, options)
42
43
  opts.footer = "List roles."
43
44
  end
44
45
  optparse.parse!(args)
45
-
46
+ # verify_args!(args:args, optparse:optparse, count:0)
47
+ options[:phrase] = args.join(" ") if args.count > 0
46
48
  connect(options)
47
- begin
48
- account = find_account_from_options(options)
49
- account_id = account ? account['id'] : nil
50
-
51
- params = {}
52
- params.merge!(parse_list_options(options))
53
- @roles_interface.setopts(options)
54
- if options[:dry_run]
55
- print_dry_run @roles_interface.dry.list(account_id, params), options
56
- return
57
- end
58
- load_whoami()
59
- json_response = @roles_interface.list(account_id, params)
60
- if options[:json]
61
- puts as_json(json_response, options, "roles")
62
- return 0
63
- elsif options[:yaml]
64
- puts as_yaml(json_response, options, "roles")
65
- return 0
66
- elsif options[:csv]
67
- puts records_as_csv(json_response['roles'], options)
68
- return 0
69
- end
49
+
50
+ account = find_account_from_options(options)
51
+ account_id = account ? account['id'] : nil
52
+ params = {}
53
+ params.merge!(parse_list_options(options))
54
+ @roles_interface.setopts(options)
55
+ if options[:dry_run]
56
+ print_dry_run @roles_interface.dry.list(account_id, params), options
57
+ return 0, nil
58
+ end
59
+ load_whoami()
60
+ json_response = @roles_interface.list(account_id, params)
61
+
62
+ render_response(json_response, options, "roles") do
70
63
  roles = json_response['roles']
71
64
  title = "Morpheus Roles"
72
65
  subtitles = []
@@ -75,22 +68,20 @@ class Morpheus::Cli::Roles
75
68
  if roles.empty?
76
69
  print cyan,"No roles found.",reset,"\n"
77
70
  else
78
- print_roles_table(roles, options.merge({is_master_account: @is_master_account}))
71
+ print cyan
72
+ columns = @is_master_account ? role_column_definitions : subtenant_role_column_definitions
73
+ print as_pretty_table(roles, columns.upcase_keys!, options)
79
74
  print_results_pagination(json_response)
80
75
  end
81
76
  print reset,"\n"
82
- return 0
83
- rescue RestClient::Exception => e
84
- print_rest_exception(e, options)
85
- exit 1
86
77
  end
78
+ return 0, nil
87
79
  end
88
80
 
89
81
  def get(args)
90
82
  options = {}
91
- params = {}
92
83
  optparse = Morpheus::Cli::OptionParser.new do |opts|
93
- opts.banner = subcommand_usage("[name]")
84
+ opts.banner = subcommand_usage("[role]")
94
85
  opts.on('-p','--permissions', "Display Permissions") do |val|
95
86
  options[:include_feature_access] = true
96
87
  end
@@ -117,19 +108,26 @@ class Morpheus::Cli::Roles
117
108
  options[:include_instance_type_access] = true
118
109
  options[:include_blueprint_access] = true
119
110
  end
120
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
121
- opts.footer = "Get details about a role.\n" +
122
- "[name] is required. This is the name or id of a role."
111
+ build_standard_get_options(opts, options)
112
+ opts.footer = <<-EOT
113
+ Get details about a role.
114
+ [role] is required. This is the name (authority) or id of a role.
115
+ EOT
123
116
  end
124
117
  optparse.parse!(args)
125
-
126
- if args.count < 1
127
- puts optparse
128
- return 1
118
+ verify_args!(args:args, optparse:optparse, min:1)
119
+ connect(options)
120
+ id_list = parse_id_list(args)
121
+ return run_command_for_each_arg(id_list) do |arg|
122
+ _get(arg, options)
129
123
  end
124
+ end
130
125
 
131
- connect(options)
132
- begin
126
+ def _get(id, options={})
127
+ args = [id] # heh
128
+ params = {}
129
+
130
+
133
131
  account = find_account_from_options(options)
134
132
  account_id = account ? account['id'] : nil
135
133
 
@@ -150,7 +148,7 @@ class Morpheus::Cli::Roles
150
148
  # refetch from show action, argh
151
149
  # json_response = @roles_interface.get(account_id, role['id'])
152
150
  # role = json_response['role']
153
-
151
+ load_whoami()
154
152
  json_response = nil
155
153
  if args[0].to_s =~ /\A\d{1,}\Z/
156
154
  json_response = @roles_interface.get(account_id, args[0].to_i)
@@ -163,27 +161,13 @@ class Morpheus::Cli::Roles
163
161
  role = json_response['role']
164
162
  end
165
163
 
166
- render_result = render_with_format(json_response, options, 'role')
167
- return 0 if render_result
168
-
164
+ render_response(json_response, options, 'role') do
165
+
169
166
  print cyan
170
167
  print_h1 "Role Details", options
171
168
  print cyan
172
- description_cols = {
173
- "ID" => 'id',
174
- "Name" => 'authority',
175
- "Description" => 'description',
176
- "Scope" => lambda {|it| it['scope'] },
177
- "Type" => lambda {|it| format_role_type(it) },
178
- "Multitenant" => lambda {|it|
179
- format_boolean(it['multitenant']).to_s + (it['multitenantLocked'] ? " (LOCKED)" : "")
180
- },
181
- "Owner" => lambda {|it| role['owner'] ? role['owner']['name'] : '' },
182
- #"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
183
- "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
184
- "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
185
- }
186
- print_description_list(description_cols, role)
169
+ columns = @is_master_account ? role_column_definitions : subtenant_role_column_definitions
170
+ print_description_list(columns, role, options)
187
171
 
188
172
  # print_h2 "Role Instance Limits", options
189
173
  # print cyan
@@ -310,13 +294,9 @@ class Morpheus::Cli::Roles
310
294
  # print "\n"
311
295
  # print cyan,bold,"Blueprint Access: #{get_access_string(json_response['globalAppTemplateAccess'])}",reset,"\n"
312
296
  end
313
-
314
297
  print reset,"\n"
315
- return 0
316
- rescue RestClient::Exception => e
317
- print_rest_exception(e, options)
318
- exit 1
319
298
  end
299
+ return 0, nil
320
300
  end
321
301
 
322
302
  def list_permissions(args)
@@ -328,14 +308,9 @@ class Morpheus::Cli::Roles
328
308
  "[role] is required. This is the name or id of a role."
329
309
  end
330
310
  optparse.parse!(args)
331
-
332
- if args.count < 1
333
- puts optparse
334
- return 1
335
- end
336
-
311
+ verify_args!(args:args, optparse:optparse, count:1)
337
312
  connect(options)
338
- begin
313
+
339
314
  account = find_account_from_options(options)
340
315
  account_id = account ? account['id'] : nil
341
316
 
@@ -406,14 +381,10 @@ class Morpheus::Cli::Roles
406
381
 
407
382
  print reset,"\n"
408
383
  return 0
409
- rescue RestClient::Exception => e
410
- print_rest_exception(e, options)
411
- exit 1
412
- end
384
+
413
385
  end
414
386
 
415
387
  def add(args)
416
- usage = "Usage: morpheus roles add [options]"
417
388
  options = {}
418
389
  params = {}
419
390
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -519,7 +490,6 @@ class Morpheus::Cli::Roles
519
490
  end
520
491
 
521
492
  def update(args)
522
- usage = "Usage: morpheus roles update [name] [options]"
523
493
  options = {}
524
494
  params = {}
525
495
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -599,7 +569,6 @@ class Morpheus::Cli::Roles
599
569
  end
600
570
 
601
571
  def remove(args)
602
- usage = "Usage: morpheus roles remove [name]"
603
572
  options = {}
604
573
  optparse = Morpheus::Cli::OptionParser.new do |opts|
605
574
  opts.banner = subcommand_usage("[name]")
@@ -1311,7 +1280,6 @@ class Morpheus::Cli::Roles
1311
1280
  ]
1312
1281
  end
1313
1282
 
1314
- "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"
1315
1283
  def update_role_option_types
1316
1284
  add_role_option_types.reject {|it| ['roleType', 'baseRole'].include?(it['fieldName']) }
1317
1285
  end
@@ -1328,17 +1296,6 @@ class Morpheus::Cli::Roles
1328
1296
  end
1329
1297
  end
1330
1298
 
1331
-
1332
- def load_whoami
1333
- whoami_response = @whoami_interface.get()
1334
- @current_user = whoami_response["user"]
1335
- if @current_user.empty?
1336
- print_red_alert "Unauthenticated. Please login."
1337
- exit 1
1338
- end
1339
- @is_master_account = whoami_response["isMasterAccount"]
1340
- end
1341
-
1342
1299
  def role_type_options
1343
1300
  [{'name' => 'User Role', 'value' => 'user'}, {'name' => 'Account Role', 'value' => 'account'}]
1344
1301
  end