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
@@ -16,9 +16,6 @@ class Morpheus::Cli::Users
16
16
  alias_subcommand :details, :get
17
17
  set_default_subcommand :list
18
18
 
19
- #todo: TOO_SIMPL_REGEX = //i
20
- # TOO_SIMPLE_ERROR = "Password too simple. Password must contain at least one uppercase letter, one lowercase letter, a number, and a symbol."
21
-
22
19
  def initialize()
23
20
  # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
24
21
  end
@@ -35,57 +32,74 @@ class Morpheus::Cli::Users
35
32
  end
36
33
 
37
34
  def list(args)
35
+ params = {}
38
36
  options = {}
39
37
  optparse = Morpheus::Cli::OptionParser.new do |opts|
40
38
  opts.banner = subcommand_usage()
41
- build_common_options(opts, options, [:account, :list, :query, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
39
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
40
+ options[:global] = true
41
+ end
42
+ opts.on('--role AUTHORITY', String, "Role Name (authority)") do |val|
43
+ params['role'] ||= []
44
+ val.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }.each do |v|
45
+ params['role'] << v
46
+ end
47
+ end
48
+ opts.on('--role-id ID', String, "Role ID") do |val|
49
+ params['roleId'] ||= []
50
+ val.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }.each do |v|
51
+ params['roleId'] << v
52
+ end
53
+ end
54
+ build_standard_list_options(opts, options, [:account])
42
55
  opts.footer = "List users."
43
56
  end
44
57
  optparse.parse!(args)
58
+ # verify_args!(args:args, optparse:optparse, count:0)
59
+ options[:phrase] = args.join(" ") if args.count > 0
45
60
  connect(options)
46
- begin
47
-
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
- @users_interface.setopts(options)
54
- if options[:dry_run]
55
- print_dry_run @users_interface.dry.list(account_id, params)
56
- return
57
- end
58
- json_response = @users_interface.list(account_id, params)
59
- render_result = render_with_format(json_response, options, 'users')
60
- return 0 if render_result
61
+ account = find_account_from_options(options)
62
+ account_id = account ? account['id'] : nil
63
+ params['global'] = true if options[:global]
64
+ params.merge!(parse_list_options(options))
65
+ @users_interface.setopts(options)
66
+ if options[:dry_run]
67
+ print_dry_run @users_interface.dry.list(account_id, params)
68
+ return 0, nil
69
+ end
70
+ json_response = @users_interface.list(account_id, params)
71
+ render_response(json_response, options, "users") do
61
72
  users = json_response['users']
62
-
63
73
  title = "Morpheus Users"
64
74
  subtitles = []
65
75
  if account
66
- subtitles << "Account: #{account['name']}".strip
76
+ subtitles << "Tenant: #{account['name']}".strip
77
+ end
78
+ if params['global'] && json_response['global']
79
+ subtitles << "(All Tenants)"
67
80
  end
68
81
  subtitles += parse_list_subtitles(options)
69
82
  print_h1 title, subtitles, options
70
83
  if users.empty?
71
84
  print cyan,"No users found.",reset,"\n"
72
85
  else
73
- print_users_table(users, options)
86
+ print cyan
87
+ print as_pretty_table(users, list_user_column_definitions, options)
74
88
  print_results_pagination(json_response)
75
89
  end
76
90
  print reset,"\n"
77
- return 0
78
-
79
- rescue RestClient::Exception => e
80
- print_rest_exception(e, options)
81
- return 1
82
91
  end
92
+ return 0, nil
83
93
  end
84
94
 
85
95
  def count(args)
96
+ params = {}
86
97
  options = {}
87
98
  optparse = Morpheus::Cli::OptionParser.new do |opts|
88
99
  opts.banner = subcommand_usage("[options]")
100
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
101
+ options[:global] = true
102
+ end
89
103
  build_common_options(opts, options, [:account, :query, :remote, :dry_run])
90
104
  opts.footer = "Get the number of users."
91
105
  end
@@ -94,7 +108,7 @@ class Morpheus::Cli::Users
94
108
  begin
95
109
  account = find_account_from_options(options)
96
110
  account_id = account ? account['id'] : nil
97
- params = {}
111
+ params['global'] = true if options[:global]
98
112
  params.merge!(parse_list_options(options))
99
113
  @users_interface.setopts(options)
100
114
  if options[:dry_run]
@@ -118,7 +132,10 @@ class Morpheus::Cli::Users
118
132
  options = {}
119
133
  params = {}
120
134
  optparse = Morpheus::Cli::OptionParser.new do |opts|
121
- opts.banner = subcommand_usage("[username]")
135
+ opts.banner = subcommand_usage("[user]")
136
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
137
+ options[:global] = true
138
+ end
122
139
  opts.on('-p','--permissions', "Display Permissions") do |val|
123
140
  options[:include_features_access] = true
124
141
  params['includeAccess'] = true
@@ -155,82 +172,51 @@ class Morpheus::Cli::Users
155
172
  opts.on('-i', '--include-none-access', "Include Items with 'None' Access in Access List") do
156
173
  options[:display_none_access] = true
157
174
  end
158
- build_common_options(opts, options, [:account, :json, :yaml, :csv, :fields, :dry_run, :remote])
159
- opts.footer = "Get details about a user." + "\n" +
160
- "[username] is required. This is the username or id of a user."
175
+ build_standard_get_options(opts, options, [:account])
176
+ opts.footer = <<-EOT
177
+ Get details about a user.
178
+ [user] is required. This is the username or id of a user. Supports 1-N arguments.
179
+ EOT
161
180
  end
162
181
  optparse.parse!(args)
163
-
164
- if args.count < 1
165
- puts optparse
166
- return 1
167
- end
168
-
182
+ verify_args!(args:args, optparse:optparse, min:1)
169
183
  connect(options)
170
- begin
171
- account = find_account_from_options(options)
172
- account_id = account ? account['id'] : nil
173
- @users_interface.setopts(options)
174
- if options[:dry_run]
175
- if args[0].to_s =~ /\A\d{1,}\Z/
176
- print_dry_run @users_interface.dry.get(account_id, args[0].to_i, params)
177
- else
178
- print_dry_run @users_interface.dry.get(account_id, {username: args[0]}, params)
179
- end
180
- return
181
- end
184
+ id_list = parse_id_list(args)
185
+ return run_command_for_each_arg(id_list) do |arg|
186
+ _get(arg, params, options)
187
+ end
188
+ end
182
189
 
190
+ def _get(id, params, options={})
191
+ args = [id] # heh
192
+ account = find_account_from_options(options)
193
+ account_id = account ? account['id'] : nil
194
+ params['global'] = true if options[:global]
195
+ @users_interface.setopts(options)
196
+ if options[:dry_run]
183
197
  if args[0].to_s =~ /\A\d{1,}\Z/
184
- user_id = args[0].to_i
198
+ print_dry_run @users_interface.dry.get(account_id, args[0].to_i, params)
185
199
  else
186
- user = find_user_by_username(account_id, args[0])
187
-
188
- if user.nil?
189
- print_red_alert "User #{args[0]} not found"
190
- exit 1
191
- end
192
- user_id = user['id']
193
- end
194
-
195
- user = @users_interface.get(account_id, user_id, params)['user']
196
-
197
- if user.nil?
198
- print_red_alert "User #{args[0]} not found"
199
- exit 1
200
+ print_dry_run @users_interface.dry.list(account_id, params.merge({username: args[0]}))
200
201
  end
202
+ return
203
+ end
201
204
 
205
+ if args[0].to_s =~ /\A\d{1,}\Z/
206
+ user_id = args[0].to_i
207
+ else
208
+ user = find_user_by_username(account_id, args[0], params)
209
+ return 1 if user.nil?
210
+ user_id = user['id']
211
+ end
212
+ # always get by id, index does not return 'access'
213
+ json_response = @users_interface.get(account_id, user_id, params)
214
+ user = json_response['user']
215
+ render_response(json_response, options, "user") do
202
216
  is_tenant_account = current_account['id'] != user['account']['id']
203
-
204
- json_response = {'user' => user}
205
-
206
- if options[:json]
207
- puts as_json(json_response, options, "user")
208
- return 0
209
- elsif options[:yaml]
210
- puts as_yaml(json_response, options, "user")
211
- return 0
212
- elsif options[:csv]
213
- puts records_as_csv([user], options)
214
- return 0
215
- end
216
-
217
217
  print_h1 "User Details", options
218
218
  print cyan
219
- description_cols = {
220
- "ID" => 'id',
221
- "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
222
- "First Name" => 'firstName',
223
- "Last Name" => 'lastName',
224
- # "Name" => 'displayName',
225
- #"Name" => lambda {|it| it['firstName'] ? it['displayName'] : '' },
226
- "Username" => 'username',
227
- "Email" => 'email',
228
- "Notifications" => lambda {|it| it['receiveNotifications'].nil? ? '' : format_boolean(it['receiveNotifications']) },
229
- "Role" => lambda {|it| format_user_role_names(it) },
230
- "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
231
- "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
232
- }
233
- print_description_list(description_cols, user)
219
+ print_description_list(user_column_definitions, user)
234
220
 
235
221
  # backward compatibility
236
222
  if user['access'].nil? && options[:include_features_access]
@@ -288,24 +274,25 @@ class Morpheus::Cli::Users
288
274
  end
289
275
  end
290
276
  end
291
- print cyan
292
277
  print reset,"\n"
293
- rescue RestClient::Exception => e
294
- print_rest_exception(e, options)
295
- return 1
296
278
  end
279
+ return 0
297
280
  end
298
281
 
299
282
  def permissions(args)
283
+ params = {}
300
284
  options = {}
301
285
  optparse = Morpheus::Cli::OptionParser.new do |opts|
302
- opts.banner = subcommand_usage("[username]")
286
+ opts.banner = subcommand_usage("[user]")
287
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
288
+ options[:global] = true
289
+ end
303
290
  build_common_options(opts, options, [:account, :json, :yaml, :csv, :fields, :dry_run, :remote])
304
291
  opts.on('-i', '--include-none-access', "Include Items with 'None' Access in Access List") do
305
292
  options[:display_none_access] = true
306
293
  end
307
294
  opts.footer = "Display Access for a user." + "\n" +
308
- "[username] is required. This is the username or id of a user."
295
+ "[user] is required. This is the username or id of a user."
309
296
  end
310
297
  optparse.parse!(args)
311
298
  verify_args!(args:args, optparse:optparse, count:1)
@@ -314,7 +301,8 @@ class Morpheus::Cli::Users
314
301
  begin
315
302
  account = find_account_from_options(options)
316
303
  account_id = account ? account['id'] : nil
317
- user = find_user_by_username_or_id(account_id, args[0])
304
+ params['global'] = true if options[:global]
305
+ user = find_user_by_username_or_id(account_id, args[0], params)
318
306
  return 1 if user.nil?
319
307
  @users_interface.setopts(options)
320
308
  if options[:dry_run]
@@ -414,10 +402,11 @@ class Morpheus::Cli::Users
414
402
  optparse = Morpheus::Cli::OptionParser.new do |opts|
415
403
  opts.banner = subcommand_usage("[username] [email] [first] [last] [options]")
416
404
  build_option_type_options(opts, options, add_user_option_types)
405
+ build_option_type_options(opts, options, add_user_advanced_option_types)
417
406
  build_common_options(opts, options, [:account, :options, :payload, :json, :dry_run])
418
407
  opts.footer = <<-EOT
419
408
  Create a new user.
420
- [username] is required. Username of the new user
409
+ [user] is required. Username of the new user
421
410
  [email] is required. Email address
422
411
  [first] is optional. First Name
423
412
  [last] is optional. Last Name
@@ -429,6 +418,9 @@ EOT
429
418
  options[:options]['email'] = args[1] if args[1]
430
419
  options[:options]['firstName'] = args[2] if args[2]
431
420
  options[:options]['lastName'] = args[3] if args[3]
421
+ if options[:options]['password']
422
+ options[:options]['passwordConfirmation'] = options[:options]['password']
423
+ end
432
424
  connect(options)
433
425
  begin
434
426
 
@@ -438,24 +430,27 @@ EOT
438
430
  payload = {}
439
431
  if options[:payload]
440
432
  payload = options[:payload]
441
- payload.deep_merge!(parse_passed_options(options))
433
+ payload.deep_merge!({'user' => parse_passed_options(options)})
442
434
  else
443
- # merge -O options into normally parsed options
444
- payload.deep_merge!(parse_passed_options(options))
435
+ payload.deep_merge!({'user' => parse_passed_options(options)})
445
436
  # remove role option_type, it is just for help display, the role prompt is separate down below
446
- prompt_option_types = add_user_option_types().reject {|it| 'role' == it['fieldName'] }
437
+ prompt_option_types = add_user_option_types().reject {|it| 'roles' == it['fieldName'] }
447
438
  v_prompt = Morpheus::Cli::OptionTypes.prompt(prompt_option_types, options[:options], @api_client, options[:params])
448
439
  params.deep_merge!(v_prompt)
449
-
440
+ # do not prompt for advanced options
441
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_user_advanced_option_types, options[:options], @api_client, options[:params])
442
+ advanced_config.deep_compact!
443
+ params.deep_merge!(advanced_config)
450
444
  # prompt for roles
451
445
  selected_roles = []
452
- selected_roles += params.delete('role').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if params['role']
453
- selected_roles += params.delete('roles').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if params['roles']
446
+ selected_roles += payload['user'].delete('roleId').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['roleId']
447
+ selected_roles += payload['user'].delete('role').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['role']
448
+ selected_roles += payload['user'].delete('roles').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['roles']
454
449
  roles = prompt_user_roles(account_id, nil, selected_roles, options)
455
450
  if !roles.empty?
456
451
  params['roles'] = roles.collect {|r| {id: r['id']} }
457
- end
458
- payload = {'user' => params}
452
+ end
453
+ payload['user'].deep_merge!(params)
459
454
  end
460
455
  if options[:dry_run] && options[:json]
461
456
  puts as_json(payload, options)
@@ -471,21 +466,16 @@ EOT
471
466
  print JSON.pretty_generate(json_response)
472
467
  print "\n"
473
468
  else
474
- username = "" # json_response['user']['username']
475
- username = payload['user']['username'] if payload['user'] && payload['user']['username']
476
- if account
477
- print_green_success "Added user #{username} to account #{account['name']}"
478
- else
479
- print_green_success "Added user #{username}"
480
- end
481
- details_options = [username]
482
- if account
483
- details_options.push "--account-id", account['id'].to_s
469
+ user = json_response['user']
470
+ username = "" # json_response['user']['username']
471
+ username = user['username'] if user
472
+ if account
473
+ print_green_success "Added user #{username} to account #{account['name']}"
474
+ else
475
+ print_green_success "Added user #{username}"
476
+ end
477
+ return _get(user['id'], {}, options)
484
478
  end
485
- get(details_options + (options[:remote] ? ["-r",options[:remote]] : []))
486
- end
487
-
488
-
489
479
  rescue RestClient::Exception => e
490
480
  print_rest_exception(e, options)
491
481
  return 1
@@ -497,8 +487,12 @@ EOT
497
487
  params = {}
498
488
  payload = {}
499
489
  optparse = Morpheus::Cli::OptionParser.new do |opts|
500
- opts.banner = subcommand_usage("[username] [options]")
490
+ opts.banner = subcommand_usage("[user] [options]")
491
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
492
+ options[:global] = true
493
+ end
501
494
  build_option_type_options(opts, options, update_user_option_types)
495
+ build_option_type_options(opts, options, update_user_advanced_option_types)
502
496
  build_common_options(opts, options, [:account, :options, :payload, :json, :dry_run])
503
497
  end
504
498
  optparse.parse!(args)
@@ -508,26 +502,38 @@ EOT
508
502
 
509
503
  account = find_account_from_options(options)
510
504
  account_id = account ? account['id'] : nil
511
-
512
- user = find_user_by_username_or_id(account_id, args[0])
505
+ params['global'] = true if options[:global]
506
+ user = find_user_by_username_or_id(account_id, args[0], params)
513
507
  return 1 if user.nil?
514
508
 
515
509
  # use --payload
510
+ payload = {}
516
511
  if options[:payload]
517
512
  payload = options[:payload]
518
- payload.deep_merge!(parse_passed_options(options))
513
+ payload.deep_merge!({'user' => parse_passed_options(options)})
519
514
  else
520
- # inject -O key=value options
521
- # payload.deep_merge!(parse_passed_options(options))
522
- params.deep_merge!(parse_passed_options(options))
523
- # user_prompt_output = Morpheus::Cli::OptionTypes.prompt(prompt_option_types, payload['user'], @api_client)
515
+ payload.deep_merge!({'user' => parse_passed_options(options)})
516
+
517
+ # remove role option_type, it is just for help display, the role prompt is separate down below
518
+ prompt_option_types = update_user_option_types().reject {|it| 'roles' == it['fieldName'] }
519
+ v_prompt = Morpheus::Cli::OptionTypes.no_prompt(prompt_option_types, options[:options], @api_client, options[:params])
520
+ v_prompt.deep_compact!
521
+ params.deep_merge!(v_prompt)
522
+ # do not prompt for advanced options
523
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_user_advanced_option_types, options[:options], @api_client, options[:params])
524
+ advanced_config.deep_compact!
525
+ params.deep_merge!(advanced_config)
526
+
524
527
  selected_roles = []
525
- selected_roles += params.delete('role').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if params['role']
526
- selected_roles += params.delete('roles').split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if params['roles']
527
- roles = prompt_user_roles(account_id, user['id'], selected_roles, options.merge(no_prompt: true))
528
- # should it allow [] (no roles) ?
529
- if !roles.empty?
530
- params['roles'] = roles.collect {|r| {id: r['id']} }
528
+ selected_roles += payload['user'].delete('roleId').to_s.split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['roleId']
529
+ selected_roles += payload['user'].delete('role').to_s.split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['role']
530
+ selected_roles += payload['user'].delete('roles').to_s.split(',').collect {|r| r.strip.empty? ? nil : r.strip}.uniq if payload['user']['roles']
531
+ if !selected_roles.empty?
532
+ roles = prompt_user_roles(account_id, user['id'], selected_roles, options.merge(no_prompt: true))
533
+ # should it allow [] (no roles) ?
534
+ if !roles.empty?
535
+ params['roles'] = roles.collect {|r| {id: r['id']} }
536
+ end
531
537
  end
532
538
  payload.deep_merge!({'user' => params})
533
539
  if payload['user'].empty? # || options[:no_prompt]
@@ -541,7 +547,7 @@ EOT
541
547
  return
542
548
  end
543
549
  json_response = @users_interface.update(account_id, user['id'], payload)
544
-
550
+ user = json_response['user']
545
551
  if options[:json]
546
552
  print JSON.pretty_generate(json_response)
547
553
  print "\n"
@@ -551,13 +557,13 @@ EOT
551
557
  username = payload['user']['username']
552
558
  end
553
559
  print_green_success "Updated user #{username}"
554
- details_options = [username]
555
- if account
556
- details_options.push "--account-id", account['id'].to_s
557
- end
558
- get(details_options + (options[:remote] ? ["-r",options[:remote]] : []))
560
+ # details_options = [username]
561
+ # if account
562
+ # details_options.push "--account-id", account['id'].to_s
563
+ # end
564
+ # get(details_options + (options[:remote] ? ["-r",options[:remote]] : []))
565
+ return _get(user["id"], {}, options)
559
566
  end
560
-
561
567
  rescue RestClient::Exception => e
562
568
  print_rest_exception(e, options)
563
569
  return 1
@@ -565,26 +571,30 @@ EOT
565
571
  end
566
572
 
567
573
  def change_password(args)
574
+ params = {}
568
575
  options = {}
569
576
  new_password = nil
570
577
  optparse = Morpheus::Cli::OptionParser.new do |opts|
571
- opts.banner = subcommand_usage("[username] [password] [options]")
578
+ opts.banner = subcommand_usage("[user] [password] [options]")
579
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
580
+ options[:global] = true
581
+ end
572
582
  # opts.on('--password VALUE', String, "New password") do |val|
573
583
  # new_password = val
574
584
  # end
575
585
  build_standard_update_options(opts, options, [:account])
576
586
  end
577
587
  optparse.parse!(args)
578
- verify_args!(args:args, optparse:optparse, min:1,max:2) # [username] [password]
588
+ verify_args!(args:args, optparse:optparse, min:1,max:2) # [user] [password]
579
589
  connect(options)
580
590
  exit_code, err = 0, nil
581
591
 
582
592
  # user can be scoped to account (tenant)
583
593
  account = find_account_from_options(options)
584
594
  account_id = account ? account['id'] : nil
585
-
595
+ params['global'] = true if options[:global]
586
596
  # fetch the user to update
587
- user = find_user_by_username_or_id(account_id, args[0])
597
+ user = find_user_by_username_or_id(account_id, args[0], params)
588
598
  return 1 if user.nil?
589
599
 
590
600
  new_password = args[1] if args[1]
@@ -644,10 +654,14 @@ EOT
644
654
  end
645
655
 
646
656
  def remove(args)
657
+ params = {}
647
658
  options = {}
648
659
  optparse = Morpheus::Cli::OptionParser.new do |opts|
649
- opts.banner = subcommand_usage("[username]")
650
- build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run])
660
+ opts.banner = subcommand_usage("[user]")
661
+ opts.on('-g','--global', "Global (All Tenants). Find users across all tenants. Default is your own tenant only.") do
662
+ options[:global] = true
663
+ end
664
+ build_standard_remove_options(opts, options, [:account])
651
665
  end
652
666
  optparse.parse!(args)
653
667
 
@@ -658,19 +672,18 @@ EOT
658
672
 
659
673
  connect(options)
660
674
  begin
661
-
662
675
  account = find_account_from_options(options)
663
676
  account_id = account ? account['id'] : nil
664
-
665
- user = find_user_by_username_or_id(account_id, args[0])
677
+ params['global'] = true if options[:global]
678
+ user = find_user_by_username_or_id(account_id, args[0], params)
666
679
  return 1 if user.nil?
667
680
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the user #{user['username']}?")
668
- exit
681
+ exit 9, "arborted"
669
682
  end
670
683
  @users_interface.setopts(options)
671
684
  if options[:dry_run]
672
685
  print_dry_run @users_interface.dry.destroy(account_id, user['id'])
673
- return
686
+ return 0
674
687
  end
675
688
  json_response = @users_interface.destroy(account_id, user['id'])
676
689
 
@@ -697,19 +710,33 @@ EOT
697
710
  {'fieldName' => 'email', 'fieldLabel' => 'Email', 'type' => 'text', 'required' => true, 'displayOrder' => 4},
698
711
  {'fieldName' => 'password', 'fieldLabel' => 'Password', 'type' => 'password', 'required' => true, 'displayOrder' => 5},
699
712
  {'fieldName' => 'passwordConfirmation', 'fieldLabel' => 'Confirm Password', 'type' => 'password', 'required' => true, 'displayOrder' => 6},
700
- {'fieldName' => 'role', 'fieldLabel' => 'Role', 'type' => 'text', 'description' => "Role names (comma separated)", 'displayOrder' => 7},
701
- {'fieldName' => 'receiveNotifications', 'fieldLabel' => 'Receive Notifications?', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true, 'displayOrder' => 58},
713
+ {'fieldName' => 'roles', 'fieldLabel' => 'Roles', 'type' => 'text', 'description' => "Role authorities or IDs (comma separated)", 'displayOrder' => 7},
714
+ {'fieldName' => 'receiveNotifications', 'fieldLabel' => 'Receive Notifications?', 'type' => 'checkbox', 'required' => false, 'defaultValue' => true, 'displayOrder' => 8}
715
+ ]
716
+ end
717
+
718
+ def add_user_advanced_option_types
719
+ [
702
720
  {'fieldName' => 'linuxUsername', 'fieldLabel' => 'Linux Username', 'type' => 'text', 'required' => false, 'displayOrder' => 9},
703
- # {'fieldName' => 'linuxPassword', 'fieldLabel' => 'Linux Password', 'type' => 'password', 'required' => false, 'displayOrder' => 10},
704
- {'fieldName' => 'windowsUsername', 'fieldLabel' => 'Windows Username', 'type' => 'text', 'required' => false, 'displayOrder' => 11},
705
- # {'fieldName' => 'windowsPassword', 'fieldLabel' => 'Windows Password', 'type' => 'text', 'required' => false, 'displayOrder' => 12},
706
- # 'linuxUsername','windowsUsername','linuxKeyPairId'
721
+ {'fieldName' => 'linuxPassword', 'fieldLabel' => 'Linux Password', 'type' => 'password', 'required' => false, 'displayOrder' => 10},
722
+ {'fieldName' => 'linuxKeyPairId', 'fieldLabel' => 'SSH Key', 'type' => 'select', 'optionSource' => 'keyPairs', 'required' => false, 'displayOrder' => 11},
723
+ {'fieldName' => 'windowsUsername', 'fieldLabel' => 'Windows Username', 'type' => 'text', 'required' => false, 'displayOrder' => 12},
724
+ {'fieldName' => 'windowsPassword', 'fieldLabel' => 'Windows Password', 'type' => 'text', 'required' => false, 'displayOrder' => 13},
707
725
  ]
708
726
  end
709
727
 
710
728
  def update_user_option_types
711
729
  add_user_option_types.collect {|it|
712
- it['required'] = false
730
+ it.delete('required')
731
+ it.delete('defaultValue')
732
+ it
733
+ }
734
+ end
735
+
736
+ def update_user_advanced_option_types
737
+ add_user_advanced_option_types.collect {|it|
738
+ it.delete('required')
739
+ it.delete('defaultValue')
713
740
  it
714
741
  }
715
742
  end
@@ -732,7 +759,7 @@ EOT
732
759
 
733
760
  if available_roles.empty?
734
761
  print_red_alert "No available roles found."
735
- return 1
762
+ exit 1
736
763
  end
737
764
  role_options = available_roles.collect {|role|
738
765
  {'name' => role['authority'], 'value' => role['id']}
@@ -754,30 +781,27 @@ EOT
754
781
  print_red_alert "Invalid Roles: #{invalid_role_names.join(', ')}"
755
782
  exit 1
756
783
  end
757
- end
758
-
759
- if roles.empty?
784
+ else
760
785
  no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
761
- if !no_prompt
762
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roleId', 'fieldLabel' => 'Role', 'type' => 'select', 'selectOptions' => role_options, 'required' => true}], options[:options])
763
- role_id = v_prompt['roleId']
764
- roles << available_roles.find {|r| r['id'].to_i == role_id.to_i }
765
- add_another_role = true
766
- while add_another_role do
767
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roleId', 'fieldLabel' => 'Another Role', 'type' => 'select', 'selectOptions' => role_options, 'required' => false}], options[:options])
768
- if v_prompt['roleId'].to_s.empty?
769
- add_another_role = false
770
- else
771
- role_id = v_prompt['roleId']
772
- roles << available_roles.find {|r| r['id'].to_i == role_id.to_i }
773
- end
774
- end
786
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roles', 'fieldLabel' => 'Role', 'type' => 'select', 'selectOptions' => role_options, 'required' => true}], options[:options])
787
+ role_id = v_prompt['roles']
788
+ roles << available_roles.find {|r| r['id'].to_i == role_id.to_i }
789
+ add_another_role = !no_prompt
790
+ while add_another_role do
791
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'roles', 'fieldLabel' => 'Another Role', 'type' => 'select', 'selectOptions' => role_options, 'required' => false}], options[:options])
792
+ if v_prompt['roles'].to_s.empty?
793
+ add_another_role = false
794
+ else
795
+ role_id = v_prompt['roles']
796
+ roles << available_roles.find {|r| r['id'].to_i == role_id.to_i }
775
797
  end
776
798
  end
777
-
778
- roles = roles.compact
779
- return roles
780
-
799
+
781
800
  end
782
801
 
802
+ roles = roles.compact
803
+ return roles
804
+
783
805
  end
806
+
807
+ end