morpheus-cli 4.2.6 → 4.2.7

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +4 -0
  4. data/lib/morpheus/api/clouds_interface.rb +14 -0
  5. data/lib/morpheus/api/guidance_interface.rb +47 -0
  6. data/lib/morpheus/api/users_interface.rb +7 -0
  7. data/lib/morpheus/cli.rb +1 -0
  8. data/lib/morpheus/cli/account_groups_command.rb +1 -1
  9. data/lib/morpheus/cli/approvals_command.rb +2 -2
  10. data/lib/morpheus/cli/apps.rb +26 -30
  11. data/lib/morpheus/cli/blueprints_command.rb +1 -1
  12. data/lib/morpheus/cli/budgets_command.rb +2 -2
  13. data/lib/morpheus/cli/change_password_command.rb +0 -1
  14. data/lib/morpheus/cli/cli_command.rb +19 -9
  15. data/lib/morpheus/cli/clouds.rb +107 -10
  16. data/lib/morpheus/cli/clusters.rb +12 -12
  17. data/lib/morpheus/cli/commands/standard/curl_command.rb +7 -0
  18. data/lib/morpheus/cli/deployments.rb +2 -2
  19. data/lib/morpheus/cli/environments_command.rb +1 -1
  20. data/lib/morpheus/cli/execution_request_command.rb +1 -1
  21. data/lib/morpheus/cli/groups.rb +1 -1
  22. data/lib/morpheus/cli/guidance_command.rb +529 -0
  23. data/lib/morpheus/cli/hosts.rb +2 -10
  24. data/lib/morpheus/cli/instances.rb +31 -13
  25. data/lib/morpheus/cli/integrations_command.rb +1 -1
  26. data/lib/morpheus/cli/jobs_command.rb +2 -2
  27. data/lib/morpheus/cli/library_container_types_command.rb +4 -4
  28. data/lib/morpheus/cli/library_instance_types_command.rb +3 -3
  29. data/lib/morpheus/cli/library_spec_templates_command.rb +1 -1
  30. data/lib/morpheus/cli/load_balancers.rb +2 -2
  31. data/lib/morpheus/cli/mixins/print_helper.rb +43 -3
  32. data/lib/morpheus/cli/mixins/provisioning_helper.rb +251 -165
  33. data/lib/morpheus/cli/network_routers_command.rb +1 -1
  34. data/lib/morpheus/cli/price_sets_command.rb +2 -2
  35. data/lib/morpheus/cli/provisioning_licenses_command.rb +1 -1
  36. data/lib/morpheus/cli/remote.rb +6 -1
  37. data/lib/morpheus/cli/reports_command.rb +1 -1
  38. data/lib/morpheus/cli/security_group_rules.rb +1 -1
  39. data/lib/morpheus/cli/security_groups.rb +13 -5
  40. data/lib/morpheus/cli/service_plans_command.rb +2 -2
  41. data/lib/morpheus/cli/user_groups_command.rb +2 -6
  42. data/lib/morpheus/cli/user_settings_command.rb +31 -5
  43. data/lib/morpheus/cli/user_sources_command.rb +3 -3
  44. data/lib/morpheus/cli/users.rb +117 -90
  45. data/lib/morpheus/cli/version.rb +1 -1
  46. data/lib/morpheus/cli/virtual_images.rb +2 -2
  47. data/lib/morpheus/cli/whitelabel_settings_command.rb +95 -15
  48. data/lib/morpheus/cli/wiki_command.rb +2 -2
  49. data/lib/morpheus/cli/workflows.rb +2 -3
  50. data/lib/morpheus/formatters.rb +14 -5
  51. metadata +4 -2
@@ -207,7 +207,7 @@ class Morpheus::Cli::NetworkRoutersCommand
207
207
  print_h2 "Tenant Permissions"
208
208
  print cyan
209
209
  description_cols = {
210
- "Visibility" => lambda{|it| it['permissions']['visibility']},
210
+ "Visibility" => lambda{|it| (it['permissions']['visibility'] || '').capitalize},
211
211
  "Tenants" => lambda{|it|
212
212
  accounts = (it['permissions']['tenantPermissions'] || {})['accounts'] || []
213
213
  accounts.count > 0 ? accounts.join(', ') : ''
@@ -64,7 +64,7 @@ class Morpheus::Cli::PriceSetsCommand
64
64
 
65
65
  price_sets = json_response['priceSets']
66
66
  if price_sets.empty?
67
- print yellow,"No price sets found.",reset,"\n"
67
+ print cyan,"No price sets found.",reset,"\n"
68
68
  else
69
69
  rows = price_sets.collect do |it|
70
70
  {
@@ -166,7 +166,7 @@ class Morpheus::Cli::PriceSetsCommand
166
166
  end
167
167
  print as_pretty_table(rows, [:id, :name, :pricing], options)
168
168
  else
169
- print yellow,"No prices.",reset,"\n"
169
+ print cyan,"No prices.",reset,"\n"
170
170
  end
171
171
  print reset,"\n"
172
172
  return 0
@@ -4,7 +4,7 @@ class Morpheus::Cli::ProvisioningLicensesCommand
4
4
  include Morpheus::Cli::CliCommand
5
5
  set_command_name :'provisioning-licenses'
6
6
  register_subcommands :list, :get, :add, :update, :remove, :reservations, :'list-types'
7
- set_command_hidden
7
+
8
8
  def connect(opts)
9
9
  @api_client = establish_remote_appliance_connection(opts)
10
10
  @provisioning_licenses_interface = @api_client.provisioning_licenses
@@ -334,6 +334,9 @@ EOT
334
334
  optparse = Morpheus::Cli::OptionParser.new do|opts|
335
335
  opts.banner = subcommand_usage("[name]")
336
336
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :quiet, :dry_run, :remote])
337
+ opts.on('-a', '--all', "Check all remotes.") do
338
+ checkall = true
339
+ end
337
340
  opts.footer = <<-EOT
338
341
  Check the status of a remote appliance.
339
342
  [name] is optional. This is the name of a remote. Default is the current remote. Can be passed as 'all'. to perform remote check-all.
@@ -341,7 +344,9 @@ This makes a request to the configured appliance url and updates the status and
341
344
  EOT
342
345
  end
343
346
  optparse.parse!(args)
344
-
347
+ if checkall == true
348
+ return _check_all_appliances(options)
349
+ end
345
350
  if args.count == 0
346
351
  id_list = ['current']
347
352
  else
@@ -513,7 +513,7 @@ class Morpheus::Cli::ReportsCommand
513
513
  report_types = json_response['reportTypes']
514
514
 
515
515
  if report_types.empty?
516
- print yellow,"No report types found.",reset,"\n"
516
+ print cyan,"No report types found.",reset,"\n"
517
517
  else
518
518
  columns = {
519
519
  "NAME" => 'name',
@@ -175,7 +175,7 @@ EOT
175
175
  rules = json_response['rules']
176
176
  print_h1 "Morpheus Security Group Rules for Security Group ID: #{security_group_id}"
177
177
  if rules.empty?
178
- print yellow,"No Security Group Rules currently configured.",reset,"\n"
178
+ print yellow,"No security group rules currently configured.",reset,"\n"
179
179
  else
180
180
  rules = rules.sort {|x,y| x["id"] <=> y["id"] }
181
181
  rules.each do |rule|
@@ -64,7 +64,7 @@ class Morpheus::Cli::SecurityGroups
64
64
  security_groups = json_response['securityGroups']
65
65
 
66
66
  if security_groups.empty?
67
- print yellow,"No security groups found.",reset,"\n"
67
+ print cyan,"No security groups found.",reset,"\n"
68
68
  else
69
69
  active_id = @active_security_group[@appliance_name.to_sym]
70
70
  # table_color = options[:color] || cyan
@@ -289,6 +289,9 @@ class Morpheus::Cli::SecurityGroups
289
289
  options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
290
290
  end
291
291
  end
292
+ opts.on('--can-manage LIST', Array, "Tenant Can Manage, comma separated list of account IDs that can manage") do |list|
293
+ options['canManage'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
294
+ end
292
295
  opts.on('--visibility [private|public]', String, "Visibility") do |val|
293
296
  options['visibility'] = val
294
297
  end
@@ -385,9 +388,10 @@ class Morpheus::Cli::SecurityGroups
385
388
  end
386
389
 
387
390
  # Tenants
388
- if options['tenants']
391
+ if options['tenants'] || options['canManage']
389
392
  payload['tenantPermissions'] = {}
390
- payload['tenantPermissions']['accounts'] = options['tenants']
393
+ payload['tenantPermissions']['accounts'] = ((options['tenants'] || []) + (options['canManage'] || [])).uniq
394
+ payload['tenantPermissions']['canManageAccounts'] = options['canManage'] if options['canManage']
391
395
  end
392
396
 
393
397
  # Visibility
@@ -459,6 +463,9 @@ class Morpheus::Cli::SecurityGroups
459
463
  options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
460
464
  end
461
465
  end
466
+ opts.on('--can-manage LIST', Array, "Tenant Can Manage, comma separated list of account IDs that can manage") do |list|
467
+ options['canManage'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
468
+ end
462
469
  opts.on('--visibility [private|public]', String, "Visibility") do |val|
463
470
  options['visibility'] = val
464
471
  end
@@ -507,9 +514,10 @@ class Morpheus::Cli::SecurityGroups
507
514
  end
508
515
 
509
516
  # Tenants
510
- if options['tenants']
517
+ if options['tenants'] || options['canManage']
511
518
  payload['tenantPermissions'] = {}
512
- payload['tenantPermissions']['accounts'] = options['tenants']
519
+ payload['tenantPermissions']['accounts'] = ((options['tenants'] || []) + (options['canManage'] || [])).uniq
520
+ payload['tenantPermissions']['canManageAccounts'] = options['canManage'] if options['canManage']
513
521
  end
514
522
 
515
523
  # Visibility
@@ -74,7 +74,7 @@ class Morpheus::Cli::ServicePlanCommand
74
74
 
75
75
  plans = json_response['servicePlans']
76
76
  if plans.empty?
77
- print yellow,"No service plans found.",reset,"\n"
77
+ print cyan,"No service plans found.",reset,"\n"
78
78
  else
79
79
  rows = plans.collect do |it|
80
80
  {
@@ -221,7 +221,7 @@ class Morpheus::Cli::ServicePlanCommand
221
221
  ]
222
222
  print as_pretty_table(rows, columns, options)
223
223
  else
224
- print yellow,"No price sets.",reset,"\n"
224
+ print cyan,"No price sets.",reset,"\n"
225
225
  end
226
226
 
227
227
  print_permissions(service_plan['permissions'], ['plans', 'groupDefaults'])
@@ -127,13 +127,9 @@ class Morpheus::Cli::UserGroupsCommand
127
127
  print_description_list(description_cols, user_group)
128
128
 
129
129
  ## Users
130
- if users.size == 1
131
- print_h2 "User (1)"
132
- else
133
- print_h2 "Users (#{users.size})"
134
- end
130
+ print_h2 "Users (#{users.size})"
135
131
  if users.size == 0
136
- print yellow,"No users",reset,"\n"
132
+ print cyan,"No users",reset,"\n"
137
133
  else
138
134
  user_columns = [
139
135
  {"ID" => lambda {|user| user['id'] } },
@@ -364,23 +364,38 @@ class Morpheus::Cli::UserSettingsCommand
364
364
  raw_args = args
365
365
  options = {}
366
366
  params = {}
367
+ client_id = nil
368
+ all_clients = false
367
369
  optparse = Morpheus::Cli::OptionParser.new do |opts|
368
370
  opts.banner = subcommand_usage("[client-id]")
371
+ opts.on("--all", "--all", "Clear tokens for all Client IDs instead of a specific client.") do
372
+ all_clients = true
373
+ end
374
+ # opts.on("--client-id", "Client ID. eg. morph-api, morph-cli") do |val|
375
+ # params['clientId'] = val.to_s
376
+ # end
369
377
  opts.on("--user-id ID", String, "User ID") do |val|
370
378
  params['userId'] = val.to_s
371
379
  end
372
380
  build_common_options(opts, options, [:payload, :options, :json, :dry_run, :quiet, :remote])
373
381
  opts.footer = "Clear API access token for a specific client.\n" +
374
- "[client-id] is required. This is the id of an api client."
382
+ "[client-id] or --all is required. This is the id of an api client."
375
383
  end
376
384
  optparse.parse!(args)
377
385
  connect(options)
378
- if args.count != 1
386
+ if args.count > 1 || (args.count == 0 && all_clients == false)
379
387
  print_error Morpheus::Terminal.angry_prompt
380
388
  puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
381
389
  return 1
382
390
  end
383
- params['clientId'] = args[0]
391
+ if args[0]
392
+ params['clientId'] = args[0]
393
+ end
394
+ if params['clientId'] == 'all'
395
+ params.delete('clientId')
396
+ all_clients = true
397
+ # clears all when clientId is omitted, no api parameter needed.
398
+ end
384
399
  begin
385
400
  payload = {}
386
401
  @user_settings_interface.setopts(options)
@@ -400,9 +415,20 @@ class Morpheus::Cli::UserSettingsCommand
400
415
  # if params['clientId'] == Morpheus::APIClient::CLIENT_ID
401
416
  # logout_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).logout
402
417
  # end
403
- print_green_success "Cleared #{params['clientId']} access token"
418
+ success_msg = "Success"
419
+ if all_clients
420
+ success_msg = "Cleared all access tokens"
421
+ else
422
+ success_msg = "Cleared #{params['clientId']} access token"
423
+ end
424
+ if params['userId']
425
+ success_msg << " for user #{params['userId']}"
426
+ end
427
+ print_green_success success_msg
404
428
  if params['clientId'] == Morpheus::APIClient::CLIENT_ID
405
- print yellow,"Your current access token is no longer valid, you will need to login again.",reset,"\n"
429
+ if params['userId'].nil? # should check against current user id
430
+ print yellow,"Your current access token is no longer valid, you will need to login again.",reset,"\n"
431
+ end
406
432
  end
407
433
  # get_args = [] + (options[:remote] ? ["-r",options[:remote]] : []) + (params['userId'] ? ['--user-id', params['userId'].to_s] : [])
408
434
  # get(get_args)
@@ -187,7 +187,7 @@ class Morpheus::Cli::UserSourcesCommand
187
187
  print_description_list(columns, user_source_config)
188
188
  # print reset,"\n"
189
189
  else
190
- print yellow,"No config found.","\n",reset
190
+ print cyan,"No config found.","\n",reset
191
191
  end
192
192
 
193
193
  role_mappings = user_source['roleMappings']
@@ -204,7 +204,7 @@ class Morpheus::Cli::UserSourcesCommand
204
204
  print as_pretty_table(role_mappings, role_mapping_columns)
205
205
  print "\n",reset
206
206
  else
207
- print yellow,"No role mappings found for this user source.","\n",reset
207
+ print cyan,"No role mappings found for this user source.","\n",reset
208
208
  end
209
209
  return 0
210
210
  rescue RestClient::Exception => e
@@ -801,7 +801,7 @@ class Morpheus::Cli::UserSourcesCommand
801
801
  ]
802
802
  print as_pretty_table(my_option_types, columns)
803
803
  else
804
- print yellow,"No option types found.","\n",reset
804
+ print cyan,"No option types found.","\n",reset
805
805
  end
806
806
 
807
807
  print reset,"\n"
@@ -10,6 +10,7 @@ require 'json'
10
10
  class Morpheus::Cli::Users
11
11
  include Morpheus::Cli::CliCommand
12
12
  include Morpheus::Cli::AccountsHelper
13
+ include Morpheus::Cli::WhoamiHelper
13
14
  register_subcommands :list, :count, :get, :add, :update, :remove, :permissions
14
15
  register_subcommands :'passwd' => :change_password
15
16
  alias_subcommand :details, :get
@@ -21,7 +22,6 @@ class Morpheus::Cli::Users
21
22
 
22
23
  def connect(opts)
23
24
  @api_client = establish_remote_appliance_connection(opts)
24
- @whoami_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).whoami
25
25
  @users_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).users
26
26
  @accounts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).accounts
27
27
  @roles_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).roles
@@ -113,25 +113,39 @@ class Morpheus::Cli::Users
113
113
 
114
114
  def get(args)
115
115
  options = {}
116
+ params = {}
116
117
  optparse = Morpheus::Cli::OptionParser.new do |opts|
117
118
  opts.banner = subcommand_usage("[username]")
118
- opts.on('-f','--feature-access', "Display Feature Access") do |val|
119
- options[:include_feature_access] = true
120
- end
121
- # opts.on(nil,'--group-access', "Display Group Access") do
122
- # options[:include_group_access] = true
123
- # end
124
- # opts.on(nil,'--cloud-access', "Display Cloud Access") do
125
- # options[:include_cloud_access] = true
126
- # end
127
- # opts.on(nil,'--instance-type-access', "Display Instance Type Access") do
128
- # options[:include_instance_type_access] = true
129
- # end
119
+ opts.on(nil,'--feature-access', "Display Feature Access") do |val|
120
+ options[:include_features_access] = true
121
+ params['includeAccess'] = true
122
+ end
123
+ opts.on(nil,'--group-access', "Display Group Access") do
124
+ options[:include_sites_access] = true
125
+ params['includeAccess'] = true
126
+ end
127
+ opts.on(nil,'--cloud-access', "Display Cloud Access") do
128
+ options[:include_zones_access] = true
129
+ params['includeAccess'] = true
130
+ end
131
+ opts.on(nil,'--instance-type-access', "Display Instance Type Access") do
132
+ options[:include_instance_types_access] = true
133
+ params['includeAccess'] = true
134
+ end
135
+ opts.on(nil,'--blueprint-access', "Display Blueprint Access") do
136
+ options[:include_app_templates_access] = true
137
+ params['includeAccess'] = true
138
+ end
130
139
  opts.on(nil,'--all', "Display All Access Lists") do
131
- options[:include_feature_access] = true
132
- options[:include_group_access] = true
133
- options[:include_cloud_access] = true
134
- options[:include_instance_type_access] = true
140
+ options[:include_features_access] = true
141
+ options[:include_sites_access] = true
142
+ options[:include_zones_access] = true
143
+ options[:include_instance_types_access] = true
144
+ options[:include_app_templates_access] = true
145
+ params['includeAccess'] = true
146
+ end
147
+ opts.on('-i', '--include-none-access', "Include Items with 'None' Access in Access List") do
148
+ options[:display_none_access] = true
135
149
  end
136
150
  build_common_options(opts, options, [:account, :json, :yaml, :csv, :fields, :dry_run, :remote])
137
151
  opts.footer = "Get details about a user." + "\n" +
@@ -151,44 +165,50 @@ class Morpheus::Cli::Users
151
165
  @users_interface.setopts(options)
152
166
  if options[:dry_run]
153
167
  if args[0].to_s =~ /\A\d{1,}\Z/
154
- print_dry_run @users_interface.dry.get(account_id, args[0].to_i, {includePermissions:true})
168
+ print_dry_run @users_interface.dry.get(account_id, args[0].to_i, params)
155
169
  else
156
- print_dry_run @users_interface.dry.get(account_id, {username: args[0]})
170
+ print_dry_run @users_interface.dry.get(account_id, {username: args[0]}, params)
157
171
  end
158
- # if options[:include_feature_access]
159
- # print_dry_run @users_interface.dry.feature_permissions(account_id, ":id")
160
- # end
161
172
  return
162
173
  end
163
- # todo: users_response = @users_interface.list(account_id, {name: name})
164
- # there may be response data outside of user that needs to be displayed
165
- user = find_user_by_username_or_id(account_id, args[0])
166
- return 1 if user.nil?
167
-
174
+
175
+ if args[0].to_s =~ /\A\d{1,}\Z/
176
+ user_id = args[0].to_i
177
+ else
178
+ user = find_user_by_username(account_id, args[0])
179
+
180
+ if user.nil?
181
+ print_red_alert "User #{args[0]} not found"
182
+ exit 1
183
+ end
184
+ user_id = user['id']
185
+ end
186
+
187
+ user = @users_interface.get(account_id, user_id, params)['user']
188
+
189
+ if user.nil?
190
+ print_red_alert "User #{args[0]} not found"
191
+ exit 1
192
+ end
193
+
194
+ is_tenant_account = current_account['id'] != user['account']['id']
195
+
168
196
  json_response = {'user' => user}
169
- # json_response['user']['featurePermissions'] = user_feature_permissions if options[:include_feature_access]
197
+
170
198
  if options[:json]
171
199
  puts as_json(json_response, options, "user")
172
- #puts as_json(@users_interface.feature_permissions(account_id, user['id']), options) if options[:include_feature_access]
173
200
  return 0
174
201
  elsif options[:yaml]
175
202
  puts as_yaml(json_response, options, "user")
176
- #puts as_yaml(@users_interface.feature_permissions(account_id, user['id']), options) if options[:include_feature_access]
177
203
  return 0
178
204
  elsif options[:csv]
179
205
  puts records_as_csv([user], options)
180
206
  return 0
181
- else
182
- user_feature_permissions_json = nil
183
- user_feature_permissions = nil
184
- if options[:include_feature_access]
185
- user_feature_permissions_json = @users_interface.feature_permissions(account_id, user['id'])
186
- # permissions (Array) has replaced featurePermissions (map)
187
- user_feature_permissions = user_feature_permissions_json['permissions'] || user_feature_permissions_json['featurePermissions']
188
- end
189
- print_h1 "User Details", options
190
- print cyan
191
- description_cols = {
207
+ end
208
+
209
+ print_h1 "User Details", options
210
+ print cyan
211
+ description_cols = {
192
212
  "ID" => 'id',
193
213
  "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
194
214
  # "First" => 'firstName',
@@ -200,34 +220,33 @@ class Morpheus::Cli::Users
200
220
  "Role" => lambda {|it| format_user_role_names(it) },
201
221
  "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
202
222
  "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
203
- }
204
- print_description_list(description_cols, user)
205
-
206
-
207
- if options[:include_feature_access] && user_feature_permissions
208
- if user_feature_permissions
209
- print_h2 "Feature Permissions", options
210
- print cyan
211
- if user_feature_permissions.is_a?(Array)
212
- rows = user_feature_permissions.collect do |it|
213
- {name: it['name'], code: it['code'], access: get_access_string(it['access']) }
214
- end
215
- print as_pretty_table(rows, [:name, :code, :access], options)
223
+ }
224
+ print_description_list(description_cols, user)
225
+
226
+ available_field_options = {'features' => 'Feature', 'sites' => 'Group', 'zones' => 'Cloud', 'instance_types' => 'Instance Type', 'app_templates' => 'Blueprint'}
227
+ available_field_options.each do |field, label|
228
+ if !(field == 'sites' && is_tenant_account) && options["include_#{field}_access".to_sym]
229
+ access = user['access'][field.split('_').enum_for(:each_with_index).collect {|word, idx| idx == 0 ? word : word.capitalize}.join]
230
+ access = access.reject {|it| it['access'] == 'none'} if !options[:display_none_access]
231
+
232
+ print_h2 "#{label} Access", options
233
+ print cyan
234
+
235
+ if access.count > 0
236
+ access.each {|it| it['access'] = get_access_string(it['access'])}
237
+
238
+ if ['features', 'instance_types'].include?(field)
239
+ print as_pretty_table(access, [:name, :code, :access], options)
216
240
  else
217
- rows = user_feature_permissions.collect do |code, access|
218
- {code: code, access: get_access_string(access) }
219
- end
220
- print as_pretty_table(rows, [:code, :access], options)
241
+ print as_pretty_table(access, [:name, :access], options)
221
242
  end
222
-
223
243
  else
224
- puts yellow,"No permissions found.",reset
244
+ println yellow,"No #{label} Access Found.",reset
225
245
  end
226
246
  end
227
-
228
- print cyan
229
- print reset,"\n"
230
247
  end
248
+ print cyan
249
+ print reset,"\n"
231
250
  rescue RestClient::Exception => e
232
251
  print_rest_exception(e, options)
233
252
  return 1
@@ -239,7 +258,10 @@ class Morpheus::Cli::Users
239
258
  optparse = Morpheus::Cli::OptionParser.new do |opts|
240
259
  opts.banner = subcommand_usage("[username]")
241
260
  build_common_options(opts, options, [:account, :json, :yaml, :csv, :fields, :dry_run, :remote])
242
- opts.footer = "Display Permissions for a user." + "\n" +
261
+ opts.on('-i', '--include-none-access', "Include Items with 'None' Access in Access List") do
262
+ options[:display_none_access] = true
263
+ end
264
+ opts.footer = "Display Access for a user." + "\n" +
243
265
  "[username] is required. This is the username or id of a user."
244
266
  end
245
267
  optparse.parse!(args)
@@ -257,46 +279,51 @@ class Morpheus::Cli::Users
257
279
  return 1 if user.nil?
258
280
  @users_interface.setopts(options)
259
281
  if options[:dry_run]
260
- print_dry_run @users_interface.dry.feature_permissions(account_id, user['id'])
282
+ print_dry_run @users_interface.dry.permissions(account_id, user['id'])
261
283
  return
262
284
  end
263
-
264
- json_response = @users_interface.feature_permissions(account_id, user['id'])
265
- # json_response['user']['featurePermissions'] = user_feature_permissions if options[:include_feature_access]
285
+
286
+ is_tenant_account = current_account['id'] != user['account']['id']
287
+
288
+ json_response = @users_interface.permissions(account_id, user['id'])
289
+
266
290
  if options[:json]
267
- puts as_json(json_response, options, 'permissions')
291
+ puts as_json(json_response, options, 'access')
268
292
  return 0
269
293
  elsif options[:yaml]
270
- puts as_yaml(json_response, options, 'permissions')
294
+ puts as_yaml(json_response, options, 'access')
271
295
  return 0
272
296
  elsif options[:csv]
273
- puts records_as_csv(json_response['permissions'], options)
297
+ puts records_as_csv(json_response['access'], options)
274
298
  return 0
275
- else
276
- user_feature_permissions = nil
277
- # permissions (Array) has replaced featurePermissions (map)
278
- user_feature_permissions = json_response['permissions'] || json_response['featurePermissions']
279
- print_h1 "User Permissions: #{user['username']}", options
280
- if user_feature_permissions
299
+ end
300
+
301
+ print_h1 "User Permissions: #{user['username']}", options
302
+
303
+ available_field_options = {'features' => 'Feature', 'sites' => 'Group', 'zones' => 'Cloud', 'instance_types' => 'Instance Type', 'app_templates' => 'Blueprint'}
304
+ available_field_options.each do |field, label|
305
+ if !(field == 'sites' && is_tenant_account)
306
+ access = json_response['access'][field.split('_').enum_for(:each_with_index).collect {|word, idx| idx == 0 ? word : word.capitalize}.join]
307
+ access = access.reject {|it| it['access'] == 'none'} if !options[:display_none_access]
308
+
309
+ print_h2 "#{label} Access", options
281
310
  print cyan
282
- if user_feature_permissions.is_a?(Array)
283
- rows = user_feature_permissions.collect do |it|
284
- {name: it['name'], code: it['code'], access: get_access_string(it['access']) }
311
+
312
+ if access.count > 0
313
+ access.each {|it| it['access'] = get_access_string(it['access'])}
314
+
315
+ if ['features', 'instance_types'].include?(field)
316
+ print as_pretty_table(access, [:name, :code, :access], options)
317
+ else
318
+ print as_pretty_table(access, [:name, :access], options)
285
319
  end
286
- print as_pretty_table(rows, [:name, :code, :access], options)
287
320
  else
288
- rows = user_feature_permissions.collect do |code, access|
289
- {code: code, access: get_access_string(access) }
290
- end
291
- print as_pretty_table(rows, [:code, :access], options)
321
+ println yellow,"No #{label} Access Found.",reset
292
322
  end
293
-
294
- else
295
- print yellow,"No permissions found.",reset,"\n"
296
323
  end
297
- print reset,"\n"
298
- return 0
299
324
  end
325
+ print cyan
326
+ print reset,"\n"
300
327
  rescue RestClient::Exception => e
301
328
  print_rest_exception(e, options)
302
329
  return 1