morpheus-cli 4.2.8 → 4.2.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api.rb +1 -1
  4. data/lib/morpheus/api/activity_interface.rb +9 -0
  5. data/lib/morpheus/api/api_client.rb +83 -27
  6. data/lib/morpheus/api/apps_interface.rb +21 -0
  7. data/lib/morpheus/api/dashboard_interface.rb +5 -21
  8. data/lib/morpheus/api/instances_interface.rb +3 -10
  9. data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
  10. data/lib/morpheus/api/invoices_interface.rb +7 -12
  11. data/lib/morpheus/api/library_layouts_interface.rb +8 -0
  12. data/lib/morpheus/api/ping_interface.rb +20 -0
  13. data/lib/morpheus/api/projects_interface.rb +33 -0
  14. data/lib/morpheus/api/setup_interface.rb +19 -36
  15. data/lib/morpheus/api/user_settings_interface.rb +0 -6
  16. data/lib/morpheus/api/whoami_interface.rb +4 -8
  17. data/lib/morpheus/benchmarking.rb +16 -26
  18. data/lib/morpheus/cli.rb +10 -5
  19. data/lib/morpheus/cli/access_token_command.rb +5 -8
  20. data/lib/morpheus/cli/activity_command.rb +146 -0
  21. data/lib/morpheus/cli/apps.rb +312 -121
  22. data/lib/morpheus/cli/archives_command.rb +1 -1
  23. data/lib/morpheus/cli/auth_command.rb +4 -11
  24. data/lib/morpheus/cli/blueprints_command.rb +196 -137
  25. data/lib/morpheus/cli/change_password_command.rb +1 -1
  26. data/lib/morpheus/cli/cli_command.rb +225 -72
  27. data/lib/morpheus/cli/cli_registry.rb +2 -2
  28. data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
  29. data/lib/morpheus/cli/clouds.rb +5 -20
  30. data/lib/morpheus/cli/clusters.rb +4 -28
  31. data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
  32. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
  33. data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
  34. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
  35. data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
  36. data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
  37. data/lib/morpheus/cli/containers_command.rb +3 -3
  38. data/lib/morpheus/cli/credentials.rb +13 -16
  39. data/lib/morpheus/cli/error_handler.rb +18 -12
  40. data/lib/morpheus/cli/errors.rb +45 -0
  41. data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
  42. data/lib/morpheus/cli/execution_request_command.rb +4 -4
  43. data/lib/morpheus/cli/groups.rb +84 -132
  44. data/lib/morpheus/cli/hosts.rb +6 -16
  45. data/lib/morpheus/cli/instances.rb +100 -183
  46. data/lib/morpheus/cli/invoices_command.rb +505 -71
  47. data/lib/morpheus/cli/library_layouts_command.rb +254 -166
  48. data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
  49. data/lib/morpheus/cli/library_option_types_command.rb +0 -96
  50. data/lib/morpheus/cli/license.rb +3 -0
  51. data/lib/morpheus/cli/login.rb +17 -37
  52. data/lib/morpheus/cli/logout.rb +9 -5
  53. data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
  54. data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
  55. data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
  56. data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
  57. data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
  58. data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
  59. data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
  60. data/lib/morpheus/cli/network_groups_command.rb +8 -2
  61. data/lib/morpheus/cli/option_types.rb +1 -1
  62. data/lib/morpheus/cli/ping.rb +252 -0
  63. data/lib/morpheus/cli/price_sets_command.rb +16 -27
  64. data/lib/morpheus/cli/prices_command.rb +34 -27
  65. data/lib/morpheus/cli/processes_command.rb +81 -7
  66. data/lib/morpheus/cli/projects_command.rb +607 -0
  67. data/lib/morpheus/cli/recent_activity_command.rb +87 -65
  68. data/lib/morpheus/cli/remote.rb +965 -974
  69. data/lib/morpheus/cli/reports_command.rb +3 -15
  70. data/lib/morpheus/cli/roles.rb +8 -31
  71. data/lib/morpheus/cli/service_plans_command.rb +25 -31
  72. data/lib/morpheus/cli/setup.rb +392 -0
  73. data/lib/morpheus/cli/shell.rb +144 -56
  74. data/lib/morpheus/cli/subnets_command.rb +71 -11
  75. data/lib/morpheus/cli/tasks.rb +3 -3
  76. data/lib/morpheus/cli/user_sources_command.rb +4 -4
  77. data/lib/morpheus/cli/users.rb +135 -109
  78. data/lib/morpheus/cli/version.rb +1 -1
  79. data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
  80. data/lib/morpheus/cli/whoami.rb +90 -129
  81. data/lib/morpheus/cli/wiki_command.rb +2 -14
  82. data/lib/morpheus/ext/rest_client.rb +36 -0
  83. data/lib/morpheus/formatters.rb +42 -5
  84. data/lib/morpheus/rest_client.rb +0 -10
  85. data/lib/morpheus/terminal.rb +41 -1
  86. data/lib/morpheus/util.rb +24 -0
  87. metadata +16 -3
  88. data/lib/morpheus/cli/command_error.rb +0 -22
@@ -355,93 +355,6 @@ class Morpheus::Cli::LibraryOptionListsCommand
355
355
 
356
356
  private
357
357
 
358
- def find_instance_type_by_name_or_id(val)
359
- if val.to_s =~ /\A\d{1,}\Z/
360
- return find_instance_type_by_id(val)
361
- else
362
- return find_instance_type_by_name(val)
363
- end
364
- end
365
-
366
- def find_instance_type_by_id(id)
367
- begin
368
- json_response = @library_instance_types_interface.get(id.to_i)
369
- return json_response['instanceType']
370
- rescue RestClient::Exception => e
371
- if e.response && e.response.code == 404
372
- print_red_alert "Instance Type not found by id #{id}"
373
- else
374
- raise e
375
- end
376
- end
377
- end
378
-
379
- def find_instance_type_by_name(name)
380
- json_response = @library_instance_types_interface.list({name: name.to_s})
381
- instance_types = json_response['instanceTypes']
382
- if instance_types.empty?
383
- print_red_alert "Instance Type not found by name #{name}"
384
- return nil
385
- elsif instance_types.size > 1
386
- print_red_alert "#{instance_types.size} instance types found by name #{name}"
387
- print_instance_types_table(instance_types, {color: red})
388
- print_red_alert "Try using ID instead"
389
- print reset,"\n"
390
- return nil
391
- else
392
- return instance_types[0]
393
- end
394
- end
395
-
396
- def print_instance_types_table(instance_types, opts={})
397
- columns = [
398
- {"ID" => lambda {|instance_type| instance_type['id'] } },
399
- {"NAME" => lambda {|instance_type| instance_type['name'] } },
400
- {"CODE" => lambda {|instance_type| instance_type['code'] } },
401
- {"TECHNOLOGY" => lambda {|instance_type| format_instance_type_technology(instance_type) } },
402
- {"CATEGORY" => lambda {|instance_type| instance_type['category'].to_s.capitalize } },
403
- {"FEATURED" => lambda {|instance_type| format_boolean instance_type['featured'] } },
404
- {"OWNER" => lambda {|instance_type| instance_type['account'] ? instance_type['account']['name'] : '' } },
405
- ]
406
- if opts[:include_fields]
407
- columns = opts[:include_fields]
408
- end
409
- print as_pretty_table(instance_types, columns, opts)
410
- end
411
-
412
- def format_instance_type_technology(instance_type)
413
- if instance_type
414
- instance_type['provisionTypeCode'].to_s.capitalize
415
- else
416
- ""
417
- end
418
- end
419
-
420
- def add_instance_type_option_types
421
- [
422
- {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
423
- {'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => true, 'displayOrder' => 2, 'description' => 'Useful shortcode for provisioning naming schemes and export reference.'},
424
- {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 3},
425
- {'fieldName' => 'category', 'fieldLabel' => 'Category', 'type' => 'select', 'optionSource' => 'categories', 'required' => true, 'displayOrder' => 4},
426
- {'fieldName' => 'logo', 'fieldLabel' => 'Icon File', 'type' => 'text', 'displayOrder' => 5},
427
- {'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'displayOrder' => 6},
428
- {'fieldName' => 'environmentPrefix', 'fieldLabel' => 'Environment Prefix', 'type' => 'text', 'displayOrder' => 7, 'description' => 'Used for exportable environment variables when tying instance types together in app contexts. If not specified a name will be generated.'},
429
- {'fieldName' => 'hasSettings', 'fieldLabel' => 'Enable Settings', 'type' => 'checkbox', 'displayOrder' => 8},
430
- {'fieldName' => 'hasAutoScale', 'fieldLabel' => 'Enable Scaling (Horizontal)', 'type' => 'checkbox', 'displayOrder' => 9},
431
- {'fieldName' => 'hasDeployment', 'fieldLabel' => 'Supports Deployments', 'type' => 'checkbox', 'displayOrder' => 10, 'description' => 'Requires a data volume be configured on each version. Files will be copied into this location.'}
432
- ]
433
- end
434
-
435
- def update_instance_type_option_types(instance_type=nil)
436
- opts = add_instance_type_option_types
437
- opts = opts.reject {|it| ["logo"].include? it['fieldName'] }
438
- if instance_type
439
- opts = add_instance_type_option_types
440
- opts.find {|opt| opt['fieldName'] == 'name'}['defaultValue'] = instance_type['name']
441
- end
442
- opts
443
- end
444
-
445
358
  def find_option_type_list_by_name_or_id(val)
446
359
  if val.to_s =~ /\A\d{1,}\Z/
447
360
  return find_option_type_list_by_id(val)
@@ -289,102 +289,6 @@ class Morpheus::Cli::LibraryOptionTypesCommand
289
289
 
290
290
  private
291
291
 
292
- def find_instance_type_by_name_or_id(val)
293
- if val.to_s =~ /\A\d{1,}\Z/
294
- return find_instance_type_by_id(val)
295
- else
296
- return find_instance_type_by_name(val)
297
- end
298
- end
299
-
300
- def find_instance_type_by_id(id)
301
- begin
302
- json_response = @library_instance_types_interface.get(id.to_i)
303
- return json_response['instanceType']
304
- rescue RestClient::Exception => e
305
- if e.response && e.response.code == 404
306
- print_red_alert "Instance Type not found by id #{id}"
307
- else
308
- raise e
309
- end
310
- end
311
- end
312
-
313
- def find_instance_type_by_name(name)
314
- json_response = @library_instance_types_interface.list({name: name.to_s})
315
- instance_types = json_response['instanceTypes']
316
- if instance_types.empty?
317
- print_red_alert "Instance Type not found by name #{name}"
318
- return nil
319
- elsif instance_types.size > 1
320
- print_red_alert "#{instance_types.size} instance types found by name #{name}"
321
- print_instance_types_table(instance_types, {color: red})
322
- print_red_alert "Try using ID instead"
323
- print reset,"\n"
324
- return nil
325
- else
326
- return instance_types[0]
327
- end
328
- end
329
-
330
- def print_instance_types_table(instance_types, opts={})
331
- columns = [
332
- {"ID" => lambda {|instance_type| instance_type['id'] } },
333
- {"NAME" => lambda {|instance_type| instance_type['name'] } },
334
- {"CODE" => lambda {|instance_type| instance_type['code'] } },
335
- {"TECHNOLOGY" => lambda {|instance_type| format_instance_type_technology(instance_type) } },
336
- {"CATEGORY" => lambda {|instance_type| instance_type['category'].to_s.capitalize } },
337
- {"FEATURED" => lambda {|instance_type| format_boolean instance_type['featured'] } },
338
- {"OWNER" => lambda {|instance_type| instance_type['account'] ? instance_type['account']['name'] : '' } },
339
- ]
340
- if opts[:include_fields]
341
- columns = opts[:include_fields]
342
- end
343
- print as_pretty_table(instance_types, columns, opts)
344
- end
345
-
346
- def format_instance_type_technology(instance_type)
347
- if instance_type
348
- instance_type['provisionTypeCode'].to_s.capitalize
349
- else
350
- ""
351
- end
352
- end
353
-
354
- def add_instance_type_option_types
355
- [
356
- {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
357
- {'fieldName' => 'code', 'fieldLabel' => 'Code', 'type' => 'text', 'required' => true, 'displayOrder' => 2, 'description' => 'Useful shortcode for provisioning naming schemes and export reference.'},
358
- {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 3},
359
- {'fieldName' => 'category', 'fieldLabel' => 'Category', 'type' => 'select', 'optionSource' => 'categories', 'required' => true, 'displayOrder' => 4},
360
- {'fieldName' => 'logo', 'fieldLabel' => 'Icon File', 'type' => 'text', 'displayOrder' => 5},
361
- {'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'displayOrder' => 6},
362
- {'fieldName' => 'environmentPrefix', 'fieldLabel' => 'Environment Prefix', 'type' => 'text', 'displayOrder' => 7, 'description' => 'Used for exportable environment variables when tying instance types together in app contexts. If not specified a name will be generated.'},
363
- {'fieldName' => 'hasSettings', 'fieldLabel' => 'Enable Settings', 'type' => 'checkbox', 'displayOrder' => 8},
364
- {'fieldName' => 'hasAutoScale', 'fieldLabel' => 'Enable Scaling (Horizontal)', 'type' => 'checkbox', 'displayOrder' => 9},
365
- {'fieldName' => 'hasDeployment', 'fieldLabel' => 'Supports Deployments', 'type' => 'checkbox', 'displayOrder' => 10, 'description' => 'Requires a data volume be configured on each version. Files will be copied into this location.'}
366
- ]
367
- end
368
-
369
- def update_instance_type_option_types(instance_type=nil)
370
- opts = add_instance_type_option_types
371
- opts = opts.reject {|it| ["logo"].include? it['fieldName'] }
372
- if instance_type
373
- opts = add_instance_type_option_types
374
- opts.find {|opt| opt['fieldName'] == 'name'}['defaultValue'] = instance_type['name']
375
- end
376
- opts
377
- end
378
-
379
- def load_balance_protocols
380
- [
381
- {'name' => 'None', 'value' => ''},
382
- {'name' => 'HTTP', 'value' => 'HTTP'},
383
- {'name' => 'HTTPS', 'value' => 'HTTPS'},
384
- {'name' => 'TCP', 'value' => 'TCP'}
385
- ]
386
- end
387
-
388
292
  # finders are in LibraryHelper
389
293
 
390
294
  # lol
@@ -9,6 +9,9 @@ class Morpheus::Cli::License
9
9
  register_subcommands :get, :install, :uninstall, :test
10
10
  # deprecated
11
11
  register_subcommands :decode, :apply
12
+
13
+ set_subcommands_hidden :decode, :apply
14
+
12
15
  #alias_subcommand :details, :get
13
16
 
14
17
  def initialize()
@@ -14,7 +14,7 @@ class Morpheus::Cli::Login
14
14
  end
15
15
 
16
16
  def connect(opts)
17
- #@api_client = establish_remote_appliance_connection(opts)
17
+ # @api_client = establish_remote_appliance_connection({:skip_verify_access_token => true, :skip_login => true}.merge(opts))
18
18
  end
19
19
 
20
20
  def usage
@@ -47,47 +47,27 @@ class Morpheus::Cli::Login
47
47
  options[:remote_token] = val
48
48
  end
49
49
  build_common_options(opts, options, [:json, :dry_run, :remote, :quiet], [:remote_username, :remote_password, :remote_token])
50
- opts.footer = "Login to a remote appliance with a username and password or an access token.\n" +
51
- "[username] is required .\n" +
52
- "[password] is required.\n" +
53
- "Logging in with username and password will make an authentication api request to obtain an access token.\n" +
54
- "The --token option can be used to login with an existing token instead of username and password.\n" +
55
- "Using --token makes a whoami api request to validate the token.\n" +
56
- "If successful, the access token will be saved with the active session for the remote appliance.\n" +
57
- "This command will first logout any active session before attempting to login.\n" +
58
- "The --test option can be used for testing credentials without updating your active session."
50
+ opts.footer = <<-EOT
51
+ Login to a remote appliance with a username and password or using an access token.
52
+ Logging in with username and password will make an authentication api request to obtain an access token.
53
+ The --token option can be used to login with a valid access token instead of username and password.
54
+ The specified token will be verified by making a whoami api request
55
+ If successful, the access token will be saved with the active session for the remote appliance.
56
+ This command will first logout any active session before attempting authorization.
57
+ The --test option is available for testing credentials without updating your active session, neithing logging you out or in.
58
+ EOT
59
59
 
60
60
  end
61
61
  optparse.parse!(args)
62
- if args.count > 2
63
- print_error Morpheus::Terminal.angry_prompt
64
- puts_error "#{command_name} list expects 0-2 arguments and received #{args.count}: #{args}\n#{optparse}"
65
- return 1
66
- end
62
+ verify_args!(args:args, max:2, optparse:optparse)
67
63
  username = args[0] if args[0]
68
64
  password = args[1] if args[1]
69
65
 
70
66
  # connect(options)
71
- if options[:remote]
72
- appliance = Morpheus::Cli::Remote.appliances[options[:remote].to_sym]
73
- if appliance
74
- @appliance_name, @appliance_url = options[:remote].to_sym, appliance[:host]
75
- else
76
- @appliance_name, @appliance_url = nil, nil
77
- end
78
- if !@appliance_name
79
- print_error red, "You have no appliance named '#{options[:remote]}' configured. See the `remote list` command.", reset, "\n"
80
- return 1
81
- end
82
- elsif options[:remote_url]
83
- # --remote-url
84
- @appliance_name, @appliance_url = nil, appliance[:remote_url]
85
- else
86
- @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
87
- if !@appliance_name
88
- print_error yellow, "Please specify a remote appliance with -r or see the command `remote use`", reset, "\n"
89
- return 1
90
- end
67
+ @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
68
+
69
+ if @remote_appliance[:authenticated]
70
+ puts "You will be automatically logged out of your current session as '#{@remote_appliance[:username]}'"
91
71
  end
92
72
 
93
73
  begin
@@ -124,9 +104,9 @@ class Morpheus::Cli::Login
124
104
  # Login Success!
125
105
  if !options[:quiet]
126
106
  if options[:test_only]
127
- print green,"Success! Credentials verified for #{wallet['username']}.", reset, "\n"
107
+ print green,"Success! Test Credentials verified for #{wallet['username']}", reset, "\n"
128
108
  else
129
- print green,"Success! Logged in to #{@appliance_name} as #{wallet['username']}.", reset, "\n"
109
+ print green,"Success! Logged in as #{wallet['username']}", reset, "\n"
130
110
  end
131
111
  end
132
112
  return 0 # , nil
@@ -15,8 +15,8 @@ class Morpheus::Cli::Logout
15
15
  @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
16
16
  end
17
17
 
18
- def connect(opts)
19
- #@api_client = establish_remote_appliance_connection(opts)
18
+ def connect(options)
19
+ @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
20
20
  end
21
21
 
22
22
  def usage
@@ -32,12 +32,16 @@ class Morpheus::Cli::Logout
32
32
  optparse = Morpheus::Cli::OptionParser.new do |opts|
33
33
  opts.banner = usage
34
34
  build_common_options(opts, options, [:remote, :quiet])
35
+ opts.footer = <<-EOT
36
+ Logout of a remote appliance.
37
+ This clears your credentials so that you will need to login again.
38
+ EOT
35
39
  end
36
40
  optparse.parse!(args)
37
- # connect(options)
41
+ verify_args!(args:args,count:0,optpare:optparse)
42
+ connect(options)
38
43
  # establish @appliance_name, @appliance_url,
39
- @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true}))
40
-
44
+ #@api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
41
45
  begin
42
46
  if !@appliance_name
43
47
  print_error Morpheus::Terminal.angry_prompt
@@ -317,6 +317,8 @@ module Morpheus::Cli::AccountsHelper
317
317
  #print reset if table_color
318
318
  end
319
319
 
320
+ ## These user access formatted methods should probably move up to PrintHelper to be more ubiquitous.
321
+
320
322
  def format_user_role_names(user)
321
323
  role_names = ""
322
324
  if user && user['roles']
@@ -327,15 +329,89 @@ module Morpheus::Cli::AccountsHelper
327
329
  role_names
328
330
  end
329
331
 
330
- def get_access_string(val)
331
- val ||= 'none'
332
- if val == 'none'
333
- "#{white}#{val.to_s.capitalize}#{cyan}"
334
- # elsif val == 'read'
335
- # "#{cyan}#{val.to_s.capitalize}#{cyan}"
332
+ def get_access_color(access)
333
+ access ||= 'none'
334
+ if access == 'none'
335
+ # maybe reset instead of white?
336
+ white
337
+ elsif access == 'read'
338
+ cyan
339
+ else
340
+ green
341
+ end
342
+ end
343
+
344
+ def get_access_string(access, return_color=cyan)
345
+ get_access_color(access) + access + return_color
346
+ # access ||= 'none'
347
+ # if access == 'none'
348
+ # "#{white}#{access.to_s}#{return_color}"
349
+ # elsif access == 'read'
350
+ # "#{cyan}#{access.to_s.capitalize}#{return_color}"
351
+ # else
352
+ # "#{green}#{access.to_s}#{return_color}"
353
+ # end
354
+ end
355
+
356
+ # this outputs a string that matches the length of all available access levels
357
+ # for outputting in a grid that looks like this:
358
+ #
359
+ # none
360
+ # full
361
+ # full
362
+ # user
363
+ # read
364
+ # full
365
+ # none
366
+ #
367
+ # Examples: format_permission_access("read")
368
+ # format_permission_access("custom", "full,custom,none")
369
+ def format_access_string(access, access_levels=nil, return_color=cyan)
370
+ access = access.to_s.downcase.strip
371
+ if access.empty?
372
+ access = "none"
373
+ end
374
+ if access_levels.nil?
375
+ access_levels = ["none","read","user","full"]
376
+ elsif access_levels.is_a?(Array)
377
+ # access_levels = access_levels
336
378
  else
337
- "#{green}#{val.to_s.capitalize}#{cyan}"
379
+ # parse values like "full,custom,none"
380
+ access_levels = [access_levels].flatten.collect {|it| it.strip.split(",") }.flatten.collect {|it| it.strip }.compact
381
+ end
382
+ # build padded string that contains access eg. 'full' or ' read'
383
+ access_levels_string = access_levels.join(",")
384
+ padded_value = ""
385
+ access_levels.each do |a|
386
+ # handle some unusual access values
387
+ # print custom, and provision where 'user' normally is at index 1
388
+ if (access == "custom" || access == "provision") && a == "user"
389
+ padded_value << access
390
+ else
391
+ if access == a
392
+ padded_value << access
393
+ else
394
+ padded_value << " " * a.size
395
+ end
396
+ end
397
+ end
398
+ # no matching access was found, so just print it in one slot
399
+ if padded_value == ""
400
+ padded_value = " " * access_levels[0].to_s.size
401
+ padded_value << access
402
+ end
403
+ # strip any extra whitespace off the end
404
+ if padded_value.size > access_levels_string.size
405
+ padded_value = padded_value.rstrip
338
406
  end
407
+ # ok build out string
408
+ out = ""
409
+ access_color = get_access_color(access)
410
+ out << access_color if access_color
411
+ out << padded_value
412
+ out << reset if access_color
413
+ out << return_color if return_color
414
+ return out
339
415
  end
340
416
 
341
417
  end
@@ -0,0 +1,41 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+
3
+ # Mixin for Morpheus::Cli command classes
4
+ # Provides common methods for working with Operations.
5
+ # This includes the Dashboard, Activity, and more... (coming soon)
6
+ module Morpheus::Cli::OperationsHelper
7
+
8
+ def self.included(klass)
9
+ klass.send :include, Morpheus::Cli::PrintHelper
10
+ end
11
+
12
+ def format_activity_severity(severity, return_color=cyan)
13
+ out = ""
14
+ status_string = severity
15
+ if status_string == 'critical'
16
+ out << "#{red}#{status_string.capitalize}#{return_color}"
17
+ elsif status_string == 'warning'
18
+ out << "#{yellow}#{status_string.capitalize}#{return_color}"
19
+ elsif status_string == 'info'
20
+ out << "#{cyan}#{status_string.capitalize}#{return_color}"
21
+ else
22
+ out << "#{cyan}#{status_string}#{return_color}"
23
+ end
24
+ out
25
+ end
26
+
27
+ def format_activity_display_object(item)
28
+ out = ""
29
+ if item['name']
30
+ out << item['name']
31
+ end
32
+ if item['objectType']
33
+ out << " (#{item['objectType']} #{item['objectId']})"
34
+ end
35
+ if item['deleted']
36
+ out << " [deleted]"
37
+ end
38
+ out
39
+ end
40
+
41
+ end