morpheus-cli 4.2.8 → 4.2.10

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 (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
@@ -1,59 +1,42 @@
1
1
  require 'morpheus/api/api_client'
2
2
  # There is no authentication required for this API.
3
3
  class Morpheus::SetupInterface < Morpheus::APIClient
4
- # def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
5
- # @access_token = access_token
6
- # @refresh_token = refresh_token
7
- # @base_url = base_url
8
- # @expires_at = expires_at
9
- # end
10
-
11
- # def initialize(base_url)
12
- # @base_url = base_url
13
- # end
14
-
15
- # no JSON here, just a 200 OK 'NOTHING TO SEE HERE'
16
- def ping(params={}, timeout=5)
17
- url = "#{@base_url}/ping"
18
- headers = {:params => params }
19
- opts = {method: :get, url: url, headers: headers, timeout: timeout}
20
- execute(opts, {parse_json: false})
4
+
5
+ # no Authorization header is required
6
+ def authorization_required?
7
+ false
21
8
  end
22
9
 
23
- def check(params={}, timeout=5)
24
- url = "#{@base_url}/api/setup/check"
25
- headers = {:params => params, 'Content-Type' => 'application/json' }
26
- execute(method: :get, url: url, headers: headers, timeout: timeout)
10
+ # health checks use a relatively small timeout by default
11
+ def default_timeout
12
+ 5
27
13
  end
28
14
 
29
15
  def get(params={})
30
- url = "#{@base_url}/api/setup"
31
- headers = {:params => params, 'Content-Type' => 'application/json' }
32
- execute(method: :get, url: url, headers: headers)
16
+ headers = {params: params}
17
+ execute(method: :get, url: "/api/setup", headers: headers)
33
18
  end
34
19
 
20
+ #this should go away and just use
21
+ def check(params={}, timeout=5)
22
+ headers = {params: params}
23
+ execute(method: :get, url: "/api/setup/check", headers: headers, timeout: timeout)
24
+ end
25
+
26
+ # you can only use this successfully one time on a fresh install.
35
27
  def init(payload={})
36
- url = "#{@base_url}/api/setup/init"
37
28
  headers = { 'Content-Type' => 'application/json' }
38
- execute(method: :post, url: url, headers: headers, payload: payload.to_json)
29
+ execute(method: :post, url: "/api/setup/init", headers: headers, payload: payload.to_json)
39
30
  end
40
31
 
41
32
  def hub_register(payload={})
42
- url = "#{@base_url}/api/setup/hub-register"
43
33
  headers = { 'Content-Type' => 'application/json' }
44
- execute(method: :post, url: url, headers: headers, payload: payload.to_json)
34
+ execute(method: :post, url: "/api/setup/hub-register", headers: headers, payload: payload.to_json)
45
35
  end
46
36
 
47
37
  def hub_login(payload={})
48
- url = "#{@base_url}/api/setup/hub-login"
49
38
  headers = { 'Content-Type' => 'application/json' }
50
- execute(method: :post, url: url, headers: headers, payload: payload.to_json)
39
+ execute(method: :post, url: "/api/setup/hub-login", headers: headers, payload: payload.to_json)
51
40
  end
52
41
 
53
- def teardown(params={})
54
- url = "#{@base_url}/api/setup/teardown"
55
- headers = { :params => params, :authorization => "Bearer #{@access_token}" }
56
- execute(method: :delete, url: url, headers: headers)
57
- end
58
-
59
42
  end
@@ -1,12 +1,6 @@
1
1
  require 'morpheus/api/api_client'
2
2
 
3
3
  class Morpheus::UserSettingsInterface < Morpheus::APIClient
4
- def initialize(access_token, refresh_token, expires_at = nil, base_url=nil)
5
- @access_token = access_token
6
- @refresh_token = refresh_token
7
- @base_url = base_url
8
- @expires_at = expires_at
9
- end
10
4
 
11
5
  def get(params={})
12
6
  url = "#{@base_url}/api/user-settings"
@@ -1,17 +1,13 @@
1
1
  require 'morpheus/api/api_client'
2
2
 
3
3
  class Morpheus::WhoamiInterface < Morpheus::APIClient
4
- def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
5
- @access_token = access_token
6
- @refresh_token = refresh_token
7
- @base_url = base_url
8
- @expires_at = expires_at
4
+
5
+ def default_timeout
6
+ 5
9
7
  end
10
8
 
11
9
  def get(params={})
12
- url = "#{@base_url}/api/whoami"
13
- headers = { params: {}, authorization: "Bearer #{@access_token}" }
14
- execute(method: :get, url: url, headers: headers, timeout: 5)
10
+ execute(method: :get, url: "/api/whoami", params: params)
15
11
  end
16
12
 
17
13
  end
@@ -229,34 +229,24 @@ module Morpheus::Benchmarking
229
229
  error_str = "#{@error}" # should inspect and format this
230
230
  out = ""
231
231
 
232
+ # show exit only if non 0
233
+ # so it looks like:
234
+ # command time [exit: 1] [error:]
235
+ # instances list foo 0.049 seconds
236
+ # foo 0.001 seconds exit: 1
237
+ out << "#{command_str.ljust(45, ' ')}"
238
+ out << "\t"
239
+ out << "#{time_str.ljust(15, ' ')}" # maybe use the format time: 0.021s
240
+ out << "\t"
232
241
  if @end_time
233
- out << "#{command_str.ljust(30, ' ')}"
234
- else
235
- out << "#{command_str.ljust(30, ' ')}"
236
- end
237
-
238
- # if @end_time
239
- # out << "finished: #{command_str.ljust(30, ' ')}"
240
- # else
241
- # out << "running: #{command_str.ljust(30, ' ')}"
242
- # end
243
-
244
- #out = "benchmark: #{command_str.ljust(22, ' ')} time: #{time_str.ljust(9, ' ')} exit: #{exit_str.ljust(2, ' ')}"
245
- # out = "benchmark: #{command_str.ljust(27, ' ')} time: #{time_str.ljust(9, ' ')} exit: #{exit_str.ljust(2, ' ')}"
246
- #out = "time: #{time_str.ljust(9, ' ')} exit: #{exit_str.ljust(2, ' ')} exec: #{command_str}"
247
- # how about a command you can copy and paste?
248
- # out = "time: #{time_str.ljust(9, ' ')} exit: #{exit_str.ljust(2, ' ')} #{command_str}"
249
- # out = "time: #{time_str.ljust(9, ' ')} exit: #{exit_str.ljust(4, ' ')} benchmark exec '#{command_str}'"
250
- if @end_time || @exit_code
251
- out << "\texit: #{exit_str.ljust(2, ' ')}"
252
- end
253
- if @end_time && @exit_code != 0 && @error
254
- out << "\terror: #{error_str.ljust(12, ' ')}"
242
+ if @exit_code && @exit_code != 0
243
+ out << "\texit: #{exit_str.ljust(2, ' ')}"
244
+ end
245
+ if @error && @error != ""
246
+ out << "\terror: #{error_str.ljust(12, ' ')}"
247
+ end
255
248
  end
256
-
257
- out << "\t#{time_str.ljust(9, ' ')}"
258
-
259
-
249
+ #out << reset
260
250
  return out
261
251
  end
262
252
 
@@ -1,8 +1,9 @@
1
1
  require 'morpheus/cli/version'
2
- require 'morpheus/cli/command_error'
2
+ require 'morpheus/cli/errors'
3
3
  require 'morpheus/rest_client'
4
4
  require 'morpheus/formatters'
5
5
  require 'morpheus/logging'
6
+ require 'morpheus/util'
6
7
  require 'term/ansicolor'
7
8
 
8
9
  Dir[File.dirname(__FILE__) + "/ext/*.rb"].each {|file| require file }
@@ -56,7 +57,7 @@ module Morpheus
56
57
  require 'morpheus/cli/cli_registry.rb'
57
58
  require 'morpheus/cli/expression_parser.rb'
58
59
  require 'morpheus/cli/dot_file.rb'
59
- require 'morpheus/cli/command_error'
60
+ require 'morpheus/cli/errors'
60
61
 
61
62
  load 'morpheus/cli/cli_command.rb'
62
63
  load 'morpheus/cli/option_types.rb'
@@ -69,17 +70,20 @@ module Morpheus
69
70
 
70
71
  # all the known commands
71
72
  load 'morpheus/cli/remote.rb'
73
+ load 'morpheus/cli/ping.rb'
74
+ load 'morpheus/cli/setup.rb'
72
75
  load 'morpheus/cli/login.rb'
73
76
  load 'morpheus/cli/logout.rb'
74
77
  load 'morpheus/cli/whoami.rb'
75
- # load 'morpheus/cli/auth_command.rb'
76
- load 'morpheus/cli/appliance_settings_command.rb'
77
78
  load 'morpheus/cli/access_token_command.rb'
78
79
  load 'morpheus/cli/user_settings_command.rb'
80
+ # load 'morpheus/cli/auth_command.rb'
79
81
  load 'morpheus/cli/dashboard_command.rb'
82
+ load 'morpheus/cli/recent_activity_command.rb' # deprecated, removing soon
83
+ load 'morpheus/cli/activity_command.rb'
84
+ load 'morpheus/cli/appliance_settings_command.rb'
80
85
  load 'morpheus/cli/power_schedules_command.rb'
81
86
  load 'morpheus/cli/execute_schedules_command.rb'
82
- load 'morpheus/cli/recent_activity_command.rb'
83
87
  load 'morpheus/cli/groups.rb'
84
88
  load 'morpheus/cli/clouds.rb'
85
89
  load 'morpheus/cli/cloud_datastores_command.rb'
@@ -166,6 +170,7 @@ module Morpheus
166
170
  load 'morpheus/cli/health_command.rb'
167
171
  load 'morpheus/cli/invoices_command.rb'
168
172
  load 'morpheus/cli/guidance_command.rb'
173
+ load 'morpheus/cli/projects_command.rb'
169
174
  # add new commands here...
170
175
 
171
176
  end
@@ -17,13 +17,10 @@ class Morpheus::Cli::AccessTokenCommand
17
17
 
18
18
  # connect overridden to skip login and return an exit_code
19
19
  def connect(options)
20
- @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true}))
20
+ @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
21
21
  # automatically get @appliance_name, @appliance_url, @wallet
22
22
  if !@appliance_name
23
- unless options[:quiet]
24
- print yellow,"Please specify a Morpheus Appliance with -r or see the command `remote use`#{reset}\n"
25
- end
26
- return 1
23
+ raise_command_error "#{command_name} requires a remote to be specified, use -r [remote] or set the active remote with `remote use`"
27
24
  end
28
25
  if !@appliance_url
29
26
  unless options[:quiet]
@@ -35,7 +32,7 @@ class Morpheus::Cli::AccessTokenCommand
35
32
  if @wallet.nil? || @wallet['access_token'].nil?
36
33
  unless options[:quiet]
37
34
  print_error yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
38
- print_error yellow,"Use the 'login' command.",reset,"\n"
35
+ print_error yellow,"Use `login` to authenticate or try passing the --username option.",reset,"\n"
39
36
  end
40
37
  return 1
41
38
  end
@@ -74,11 +71,11 @@ class Morpheus::Cli::AccessTokenCommand
74
71
  print_h1 "Morpheus Credentials", options
75
72
  description_cols = {
76
73
  "Username" => lambda {|wallet| wallet['username'] },
77
- "Remote" => lambda {|wallet| "#{display_appliance(@appliance_name, @appliance_url)}" },
78
74
  "Access Token" => lambda {|wallet| wallet['access_token'] },
79
75
  "Refresh Token" => lambda {|wallet| wallet['refresh_token'] },
80
76
  "Login Date" => lambda {|wallet| format_local_dt(wallet['login_date']) },
81
77
  "Expire Date" => lambda {|wallet| wallet['expire_date'] ? format_local_dt(wallet['expire_date']) : "" },
78
+ # "Remote" => lambda {|wallet| display_appliance(@appliance_name, @appliance_url) },
82
79
  }
83
80
  print cyan
84
81
  puts as_description_list(@wallet, description_cols)
@@ -130,7 +127,7 @@ class Morpheus::Cli::AccessTokenCommand
130
127
  # if @wallet.nil? || @wallet['access_token'].nil?
131
128
  # unless options[:quiet]
132
129
  # print_error yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
133
- # print_error yellow,"Use the 'login' command.",reset,"\n"
130
+ # print_error yellow,"Use `login` to authenticate or try passing the --username option.",reset,"\n"
134
131
  # end
135
132
  # return 1
136
133
  # end
@@ -0,0 +1,146 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ class Morpheus::Cli::ActivityCommand
4
+ include Morpheus::Cli::CliCommand
5
+ include Morpheus::Cli::OperationsHelper
6
+ include Morpheus::Cli::OptionSourceHelper
7
+
8
+ set_command_name :'activity'
9
+ register_subcommands :list
10
+
11
+ def connect(opts)
12
+ @api_client = establish_remote_appliance_connection(opts)
13
+ @activity_interface = @api_client.activity
14
+ end
15
+
16
+ def handle(args)
17
+ handle_subcommand(args)
18
+ end
19
+
20
+ def list(args)
21
+ exit_code, err = 0, nil
22
+ params, options = {}, {}
23
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
24
+ opts.banner = subcommand_usage()
25
+ opts.on('-t','--type TYPE', "Activity Type eg. Provisioning, Admin") do |val|
26
+ options[:type] ||= []
27
+ options[:type] << val
28
+ end
29
+ opts.on('--timeframe TIMEFRAME', String, "Timeframe, eg. hour,day,today,yesterday,week,month,3months. Default is month") do |val|
30
+ options[:timeframe] = val
31
+ end
32
+ opts.on('--start TIMESTAMP','--start TIMESTAMP', "Start date to search for activity, can be used instead of --timeframe. Default is a month ago.") do |val|
33
+ options[:start] = parse_time(val) #.utc.iso8601
34
+ end
35
+ opts.on('--end TIMESTAMP','--end TIMESTAMP', "Start date to search for activity. Default is the current time.") do |val|
36
+ options[:end] = parse_time(val) #.utc.iso8601
37
+ end
38
+ opts.on('-u', '--user USER', "User Name or ID" ) do |val|
39
+ options[:user] = val
40
+ end
41
+ opts.on( '--tenant TENANT', String, "Tenant Name or ID" ) do |val|
42
+ options[:tenant] = val
43
+ end
44
+ build_standard_list_options(opts, options)
45
+ opts.footer = <<-EOT
46
+ List activity.
47
+ The default timeframe a month ago up until now, with the most recent activity seen first.
48
+ The option --timeframe or --start and --end can be used to customized the date period
49
+ EOT
50
+ end
51
+ # parse options
52
+ optparse.parse!(args)
53
+ # parse arguments
54
+ verify_args!(args:args, count:0, optparse:optparse)
55
+ # establish connection to @remote_appliance
56
+ connect(options)
57
+ # construct request
58
+ # inject -Q PARAMS and standard list options phrase,max,sort,search
59
+ params.merge!(parse_list_options(options))
60
+ # --type
61
+ if options[:type]
62
+ params['type'] = [options[:type]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip }
63
+ end
64
+ # --timeframe
65
+ if options[:timeframe]
66
+ params['timeframe'] = options[:timeframe]
67
+ end
68
+ # --start
69
+ if options[:start]
70
+ params['start'] = options[:start]
71
+ end
72
+ # --end
73
+ if options[:end]
74
+ params['end'] = options[:end]
75
+ end
76
+ # --user
77
+ if options[:user]
78
+ user_ids = parse_user_id_list(options[:user])
79
+ return 1 if user_ids.nil?
80
+ params['userId'] = user_ids
81
+ end
82
+ # --tenant
83
+ if options[:tenant]
84
+ tenant_ids = parse_tenant_id_list(options[:tenant])
85
+ return 1 if tenant_ids.nil?
86
+ params['tenantId'] = tenant_ids[0]
87
+ end
88
+
89
+ # execute the api request
90
+ @activity_interface.setopts(options)
91
+ if options[:dry_run]
92
+ print_dry_run @activity_interface.dry.list(params)
93
+ return 0, nil
94
+ end
95
+ json_response = @activity_interface.list(params)
96
+ activity = json_response["activity"]
97
+ render_response(json_response, options, "activity") do
98
+ title = "Morpheus Activity"
99
+ subtitles = []
100
+ subtitles += parse_list_subtitles(options)
101
+ if json_response["meta"] && json_response["meta"]["startDate"]
102
+ subtitles << "#{format_local_dt(json_response["meta"]["startDate"])} - #{format_local_dt(json_response["meta"]["endDate"])}"
103
+ end
104
+ if options[:start]
105
+ subtitles << "Start: #{options[:start]}"
106
+ end
107
+ if options[:end]
108
+ subtitles << "End: #{options[:end]}"
109
+ end
110
+ print_h1 title, subtitles, options
111
+ if activity.empty?
112
+ print yellow, "No activity found.",reset,"\n"
113
+ else
114
+ columns = [
115
+ # {"SEVERITY" => lambda {|record| format_activity_severity(record['severity']) } },
116
+ {"TYPE" => lambda {|record| record['activityType'] } },
117
+ {"NAME" => lambda {|record| record['name'] } },
118
+ {"RESOURCE" => lambda {|record| "#{record['objectType']} #{record['objectId']}" } },
119
+ {"MESSAGE" => lambda {|record| record['message'] || '' } },
120
+ {"USER" => lambda {|record| record['user'] ? record['user']['username'] : record['userName'] } },
121
+ #{"DATE" => lambda {|record| "#{format_duration_ago(record['ts'] || record['timestamp'])}" } },
122
+ {"DATE" => lambda {|record|
123
+ # show full time if searching for custom timerange, otherwise the default is to show relative time
124
+ if params['start'] || params['end'] || params['timeframe']
125
+ "#{format_local_dt(record['ts'] || record['timestamp'])}"
126
+ else
127
+ "#{format_duration_ago(record['ts'] || record['timestamp'])}"
128
+ end
129
+
130
+ } },
131
+ ]
132
+ print as_pretty_table(activity, columns, options)
133
+ print_results_pagination(json_response)
134
+ end
135
+ print reset,"\n"
136
+ end
137
+ if activity.empty?
138
+ return 1, "0 activity found"
139
+ else
140
+ return 0, nil
141
+ end
142
+ end
143
+
144
+ protected
145
+
146
+ end
@@ -11,13 +11,17 @@ require 'morpheus/cli/mixins/logs_helper'
11
11
 
12
12
  class Morpheus::Cli::Apps
13
13
  include Morpheus::Cli::CliCommand
14
- include Morpheus::Cli::AccountsHelper
14
+ include Morpheus::Cli::AccountsHelper # needed? replace with OptionSourceHelper
15
+ include Morpheus::Cli::OptionSourceHelper
15
16
  include Morpheus::Cli::ProvisioningHelper
16
17
  include Morpheus::Cli::ProcessesHelper
17
18
  include Morpheus::Cli::LogsHelper
18
19
  set_command_name :apps
19
20
  set_command_description "View and manage apps."
20
21
  register_subcommands :list, :count, :get, :view, :add, :update, :remove, :cancel_removal, :add_instance, :remove_instance, :logs, :security_groups, :apply_security_groups, :history
22
+ register_subcommands :'prepare-apply' => :prepare_apply
23
+ register_subcommands :apply
24
+ register_subcommands :refresh
21
25
  register_subcommands :stop, :start, :restart
22
26
  register_subcommands :wiki, :update_wiki
23
27
  #register_subcommands :firewall_disable, :firewall_enable
@@ -51,17 +55,38 @@ class Morpheus::Cli::Apps
51
55
  end
52
56
 
53
57
  def list(args)
58
+ params = {}
54
59
  options = {}
55
60
  optparse = Morpheus::Cli::OptionParser.new do |opts|
56
61
  opts.banner = subcommand_usage()
57
- opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
58
- options[:created_by] = val
62
+ opts.on( '-t', '--type TYPE', "Filter by type" ) do |val|
63
+ options[:type] = val
64
+ end
65
+ opts.on( '--blueprint BLUEPRINT', "Blueprint Name or ID" ) do |val|
66
+ options[:blueprint] = val
59
67
  end
68
+ opts.on( '--owner USER', "Owner Username or ID" ) do |val|
69
+ options[:owner] = val
70
+ end
71
+ opts.on( '--created-by USER', "[DEPRECATED] Alias for --owner" ) do |val|
72
+ options[:owner] = val
73
+ end
74
+ opts.add_hidden_option('--created-by')
60
75
  opts.on('--details', "Display more details: memory and storage usage used / max values." ) do
61
76
  options[:details] = true
62
77
  end
63
78
  opts.on('--pending-removal', "Include apps pending removal.") do
64
- options[:pendingRemoval] = true
79
+ options[:showDeleted] = true
80
+ end
81
+ opts.on('--pending-removal-only', "Only apps pending removal.") do
82
+ options[:deleted] = true
83
+ end
84
+ opts.on('--environment ENV', "Filter by environment code (appContext)") do |val|
85
+ # environment means appContext
86
+ params['environment'] = (params['environment'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" }
87
+ end
88
+ opts.on('--status STATUS', "Filter by status.") do |val|
89
+ params['status'] = (params['status'] || []) + val.to_s.split(',').collect {|s| s.strip }.select {|s| s != "" }
65
90
  end
66
91
  build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
67
92
  opts.footer = "List apps."
@@ -74,16 +99,44 @@ class Morpheus::Cli::Apps
74
99
  end
75
100
  connect(options)
76
101
  begin
77
- params = {}
102
+ if options[:type]
103
+ params['type'] = [options[:type]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip }
104
+ end
105
+ if options[:blueprint]
106
+ blueprint_ids = [options[:blueprint]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip }
107
+ params['blueprintId'] = blueprint_ids.collect do |blueprint_id|
108
+ if blueprint_id.to_s =~ /\A\d{1,}\Z/
109
+ return blueprint_id
110
+ else
111
+ blueprint = find_blueprint_by_name_or_id(blueprint_id)
112
+ return 1 if blueprint.nil?
113
+ blueprint['id']
114
+ end
115
+ end
116
+ end
117
+ if options[:owner]
118
+ owner_ids = [options[:owner]].flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip }
119
+ params['ownerId'] = owner_ids.collect do |owner_id|
120
+ if owner_id.to_s =~ /\A\d{1,}\Z/
121
+ return owner_id
122
+ else
123
+ user = find_available_user_option(owner_id)
124
+ return 1 if user.nil?
125
+ user['id']
126
+ end
127
+ end
128
+ end
78
129
  params.merge!(parse_list_options(options))
79
130
  account = nil
80
- if options[:created_by]
81
- created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:created_by])
131
+ if options[:owner]
132
+ created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner])
82
133
  return if created_by_ids.nil?
83
134
  params['createdBy'] = created_by_ids
135
+ # params['ownerId'] = created_by_ids # 4.2.1+
84
136
  end
85
137
 
86
- params['showDeleted'] = true if options[:pendingRemoval]
138
+ params['showDeleted'] = options[:showDeleted] if options.key?(:showDeleted)
139
+ params['deleted'] = options[:deleted] if options.key?(:deleted)
87
140
 
88
141
  @apps_interface.setopts(options)
89
142
  if options[:dry_run]
@@ -125,9 +178,13 @@ class Morpheus::Cli::Apps
125
178
  options = {}
126
179
  optparse = Morpheus::Cli::OptionParser.new do |opts|
127
180
  opts.banner = subcommand_usage("[options]")
128
- opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
129
- options[:created_by] = val
181
+ opts.on( '--owner USER', "Owner Username or ID" ) do |val|
182
+ options[:owner] = val
183
+ end
184
+ opts.on( '--created-by USER', "Alias for --owner" ) do |val|
185
+ options[:owner] = val
130
186
  end
187
+ opts.add_hidden_option('--created-by')
131
188
  opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
132
189
  options[:phrase] = phrase
133
190
  end
@@ -140,10 +197,11 @@ class Morpheus::Cli::Apps
140
197
  params = {}
141
198
  params.merge!(parse_list_options(options))
142
199
  account = nil
143
- if options[:created_by]
144
- created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:created_by])
200
+ if options[:owner]
201
+ created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner])
145
202
  return if created_by_ids.nil?
146
203
  params['createdBy'] = created_by_ids
204
+ # params['ownerId'] = created_by_ids # 4.2.1+
147
205
  end
148
206
  @apps_interface.setopts(options)
149
207
  if options[:dry_run]
@@ -414,6 +472,7 @@ class Morpheus::Cli::Apps
414
472
  instance_prompt_options[:help_field_prefix] = help_field_prefix
415
473
  instance_prompt_options[:options][:help_field_prefix] = help_field_prefix
416
474
  instance_prompt_options[:locked_fields] = scoped_instance_config['lockedFields']
475
+ instance_prompt_options[:for_app] = true
417
476
  # this provisioning helper method handles all (most) of the parsing and prompting
418
477
  instance_config_payload = prompt_new_instance(instance_prompt_options)
419
478
 
@@ -622,10 +681,18 @@ class Morpheus::Cli::Apps
622
681
  "ID" => 'id',
623
682
  "Name" => 'name',
624
683
  "Description" => 'description',
684
+ "Type" => lambda {|it|
685
+ if it['type']
686
+ format_blueprint_type(it['type'])
687
+ else
688
+ format_blueprint_type(it['blueprint'] ? it['blueprint']['type'] : nil)
689
+ end
690
+ },
625
691
  "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : '' },
626
692
  "Group" => lambda {|it| it['group'] ? it['group']['name'] : it['siteId'] },
627
693
  "Environment" => lambda {|it| it['appContext'] },
628
- "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
694
+ "Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
695
+ #"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
629
696
  "Tiers" => lambda {|it|
630
697
  # it['instanceCount']
631
698
  tiers = []
@@ -633,7 +700,7 @@ class Morpheus::Cli::Apps
633
700
  app_tiers.each do |app_tier|
634
701
  tiers << app_tier['tier']
635
702
  end
636
- "#{tiers.collect {|it| it.is_a?(Hash) ? it['name'] : it }.join(',')}"
703
+ "(#{(tiers || []).size()}) #{tiers.collect {|it| it.is_a?(Hash) ? it['name'] : it }.join(',')}"
637
704
  },
638
705
  "Instances" => lambda {|it|
639
706
  # it['instanceCount']
@@ -660,9 +727,9 @@ class Morpheus::Cli::Apps
660
727
 
661
728
  description_cols["Removal Date"] = lambda {|it| format_local_dt(it['removalDate'])} if app['status'] == 'pendingRemoval'
662
729
 
663
- if app['blueprint'].nil?
664
- description_cols.delete("Blueprint")
665
- end
730
+ # if app['blueprint'].nil?
731
+ # description_cols.delete("Blueprint")
732
+ # end
666
733
  # if app['description'].nil?
667
734
  # description_cols.delete("Description")
668
735
  # end
@@ -675,7 +742,8 @@ class Morpheus::Cli::Apps
675
742
  end
676
743
 
677
744
  if app_tiers.empty?
678
- puts yellow, "This app is empty", reset
745
+ #puts yellow, "This app is empty", reset
746
+ print reset,"\n"
679
747
  else
680
748
  app_tiers.each do |app_tier|
681
749
  # print_h2 "Tier: #{app_tier['tier']['name']}", options
@@ -737,7 +805,7 @@ class Morpheus::Cli::Apps
737
805
  end
738
806
 
739
807
  def update(args)
740
- options = {}
808
+ params, payload, options = {}, {}, {}
741
809
  optparse = Morpheus::Cli::OptionParser.new do |opts|
742
810
  opts.banner = subcommand_usage("[app] [options]")
743
811
  #build_option_type_options(opts, options, update_app_option_types(false))
@@ -753,6 +821,9 @@ class Morpheus::Cli::Apps
753
821
  opts.on( '--environment VALUE', String, "Environment" ) do |val|
754
822
  options[:environment] = val
755
823
  end
824
+ opts.on( '--owner USER', "Owner Username or ID" ) do |val|
825
+ options[:owner] = val == 'null' ? nil : val
826
+ end
756
827
  build_common_options(opts, options, [:options, :payload, :json, :dry_run])
757
828
  opts.footer = "Update an app.\n" +
758
829
  "[app] is required. This is the name or id of an app."
@@ -768,64 +839,223 @@ class Morpheus::Cli::Apps
768
839
  begin
769
840
  app = find_app_by_name_or_id(args[0])
770
841
  return 1 if app.nil?
771
-
772
- payload = {}
773
842
  if options[:payload]
774
843
  payload = options[:payload]
775
- else
776
- payload = {
777
- 'app' => {id: app["id"]}
778
- }
779
- params = options[:options] || {}
780
- if options[:name]
781
- params['name'] = options[:name]
782
- end
783
- if options[:description]
784
- params['description'] = options[:description]
785
- end
786
- if options[:environment]
787
- # params['environment'] = options[:environment]
788
- params['appContext'] = options[:environment]
789
- end
790
- if options[:group]
791
- group = find_group_by_name_or_id_for_provisioning(options[:group])
792
- return 1 if group.nil?
793
- params['group'] = {'id' => group['id'], 'name' => group['name']}
794
- end
795
- if params.empty?
796
- print_red_alert "Specify at least one option to update"
797
- puts optparse
798
- return 1
799
- end
800
- payload['app'].merge!(params)
801
- # api bug requires this to be at the root level as well right now
802
- if payload['app'] && payload['app']['group']
803
- payload['group'] = payload['app']['group']
844
+ end
845
+ payload['app'] ||= {}
846
+ payload.deep_merge!({'app' => parse_passed_options(options)})
847
+ if options[:name]
848
+ payload['app']['name'] = options[:name]
849
+ end
850
+ if options[:description]
851
+ payload['app']['description'] = options[:description]
852
+ end
853
+ if options[:environment]
854
+ # payload['app']['environment'] = options[:environment]
855
+ payload['app']['appContext'] = options[:environment]
856
+ end
857
+ if options[:group]
858
+ group = find_group_by_name_or_id_for_provisioning(options[:group])
859
+ return 1 if group.nil?
860
+ payload['app']['group'] = {'id' => group['id'], 'name' => group['name']}
861
+ end
862
+ if options.key?(:owner)
863
+ owner_id = options[:owner]
864
+ if owner_id.to_s.empty?
865
+ # allow clearing
866
+ owner_id = nil
867
+ elsif options[:owner]
868
+ if owner_id.to_s =~ /\A\d{1,}\Z/
869
+ # allow id without lookup
870
+ else
871
+ user = find_available_user_option(owner_id)
872
+ return 1 if user.nil?
873
+ owner_id = user['id']
874
+ end
804
875
  end
876
+ payload['app']['ownerId'] = owner_id
877
+ end
878
+ if payload['app'] && payload['app'].empty?
879
+ payload.delete('app')
805
880
  end
881
+ if payload.empty?
882
+ raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty?
883
+ end
884
+
806
885
  @apps_interface.setopts(options)
807
886
  if options[:dry_run]
808
887
  print_dry_run @apps_interface.dry.update(app["id"], payload)
809
888
  return
810
889
  end
811
-
812
890
  json_response = @apps_interface.update(app["id"], payload)
813
- if options[:json]
814
- print JSON.pretty_generate(json_response)
815
- print "\n"
891
+ render_result = render_with_format(json_response, options)
892
+ return 0 if render_result
893
+ print_green_success "Updated app #{app['name']}"
894
+ get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
895
+ return 0
896
+ rescue RestClient::Exception => e
897
+ print_rest_exception(e, options)
898
+ exit 1
899
+ end
900
+ end
901
+
902
+ def refresh(args)
903
+ params, payload, options = {}, {}, {}
904
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
905
+ opts.banner = subcommand_usage("[app] [options]")
906
+ build_standard_update_options(opts, options, [:auto_confirm])
907
+ opts.footer = <<-EOT
908
+ Refresh an app.
909
+ [app] is required. This is the name or id of an app.
910
+ This is only supported by certain types of apps.
911
+ EOT
912
+ end
913
+ optparse.parse!(args)
914
+ if args.count != 1
915
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(', ')}\n#{optparse}"
916
+ end
917
+ connect(options)
918
+
919
+ begin
920
+ app = find_app_by_name_or_id(args[0])
921
+ return 1 if app.nil?
922
+ # construct request
923
+ params.merge!(parse_query_options(options))
924
+ payload = {}
925
+ if options[:payload]
926
+ payload = options[:payload]
927
+ payload.deep_merge!(parse_passed_options(options))
816
928
  else
817
- print_green_success "Updated app #{app['name']}"
818
- # print details
819
- get_args = [app['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
820
- get(get_args)
929
+ payload.deep_merge!(parse_passed_options(options))
930
+ # raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty?
931
+ end
932
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to refresh this app: #{app['name']}?")
933
+ return 9, "aborted command"
934
+ end
935
+ @apps_interface.setopts(options)
936
+ if options[:dry_run]
937
+ print_dry_run @apps_interface.dry.refresh(app["id"], params, payload)
938
+ return
821
939
  end
940
+ json_response = @apps_interface.refresh(app["id"], params, payload)
941
+ render_result = render_with_format(json_response, options)
942
+ return 0 if render_result
943
+ print_green_success "Refreshed app #{app['name']}"
944
+ return get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
945
+ rescue RestClient::Exception => e
946
+ print_rest_exception(e, options)
947
+ exit 1
948
+ end
949
+ end
822
950
 
951
+ def prepare_apply(args)
952
+ params, payload, options = {}, {}, {}
953
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
954
+ opts.banner = subcommand_usage("[app] [options]")
955
+ build_standard_update_options(opts, options, [:auto_confirm])
956
+ opts.footer = <<-EOT
957
+ Prepare to apply an app.
958
+ [app] is required. This is the name or id of an app.
959
+ Template parameter values can be applied with -O templateParameter.foo=bar
960
+ This only prints the app configuration that would be applied.
961
+ It does not make any updates.
962
+ This is only supported by certain types of apps.
963
+ EOT
964
+ end
965
+ optparse.parse!(args)
966
+ if args.count != 1
967
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(', ')}\n#{optparse}"
968
+ end
969
+ connect(options)
970
+
971
+ begin
972
+ app = find_app_by_name_or_id(args[0])
973
+ return 1 if app.nil?
974
+ # construct request
975
+ params.merge!(parse_query_options(options))
976
+ payload = {}
977
+ if options[:payload]
978
+ payload = options[:payload]
979
+ payload.deep_merge!(parse_passed_options(options))
980
+ else
981
+ payload.deep_merge!(parse_passed_options(options))
982
+ # raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty?
983
+ end
984
+ @apps_interface.setopts(options)
985
+ if options[:dry_run]
986
+ print_dry_run @apps_interface.dry.prepare_apply(app["id"], params, payload)
987
+ return
988
+ end
989
+ json_response = @apps_interface.prepare_apply(app["id"], params, payload)
990
+ render_result = render_with_format(json_response, options)
991
+ return 0 if render_result
992
+ # print_green_success "Prepared to apply app: #{app['name']}"
993
+ print_h1 "Prepared App: #{app['name']}"
994
+ app_config = json_response['data']
995
+ # app_config = json_response if app_config.nil?
996
+ puts as_yaml(app_config, options)
997
+ #return get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
998
+ print "\n", reset
999
+ return 0
823
1000
  rescue RestClient::Exception => e
824
1001
  print_rest_exception(e, options)
825
1002
  exit 1
826
1003
  end
827
1004
  end
828
1005
 
1006
+ def apply(args)
1007
+ params, payload, options = {}, {}, {}
1008
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1009
+ opts.banner = subcommand_usage("[app] [options]")
1010
+ build_standard_update_options(opts, options, [:auto_confirm])
1011
+ opts.footer = <<-EOT
1012
+ Apply an app.
1013
+ [app] is required. This is the name or id of an app.
1014
+ Template parameter values can be applied with -O templateParameter.foo=bar
1015
+ This is a way to apply an app with new configuration parameters to an app.
1016
+ This prints the app configuration that would be applied.
1017
+ It does not make any updates.
1018
+ This is only supported by certain types of apps.
1019
+ EOT
1020
+ end
1021
+ optparse.parse!(args)
1022
+ if args.count != 1
1023
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(', ')}\n#{optparse}"
1024
+ end
1025
+ connect(options)
1026
+
1027
+ begin
1028
+ app = find_app_by_name_or_id(args[0])
1029
+ return 1 if app.nil?
1030
+ # construct request
1031
+ params.merge!(parse_query_options(options))
1032
+ payload = {}
1033
+ if options[:payload]
1034
+ payload = options[:payload]
1035
+ payload.deep_merge!(parse_passed_options(options))
1036
+ else
1037
+ payload.deep_merge!(parse_passed_options(options))
1038
+ # raise_command_error "Specify at least one option to update.\n#{optparse}" if payload.empty?
1039
+ end
1040
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to apply this app: #{app['name']}?")
1041
+ return 9, "aborted command"
1042
+ end
1043
+ @apps_interface.setopts(options)
1044
+ if options[:dry_run]
1045
+ print_dry_run @apps_interface.dry.apply(app["id"], params, payload)
1046
+ return
1047
+ end
1048
+ json_response = @apps_interface.apply(app["id"], params, payload)
1049
+ render_result = render_with_format(json_response, options)
1050
+ return 0 if render_result
1051
+ print_green_success "Applied app #{app['name']}"
1052
+ #return get([app['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
1053
+ return 0
1054
+ rescue RestClient::Exception => e
1055
+ print_rest_exception(e, options)
1056
+ exit 1
1057
+ end
1058
+ end
829
1059
 
830
1060
  def add_instance(args)
831
1061
  options = {}
@@ -1170,6 +1400,7 @@ class Morpheus::Cli::Apps
1170
1400
  end
1171
1401
  end
1172
1402
 
1403
+
1173
1404
  def stop(args)
1174
1405
  options = {}
1175
1406
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -1640,23 +1871,11 @@ class Morpheus::Cli::Apps
1640
1871
  link << "#!#{options[:link_tab]}"
1641
1872
  end
1642
1873
 
1643
- open_command = nil
1644
- if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
1645
- open_command = "start #{link}"
1646
- elsif RbConfig::CONFIG['host_os'] =~ /darwin/
1647
- open_command = "open #{link}"
1648
- elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
1649
- open_command = "xdg-open #{link}"
1650
- end
1651
-
1652
1874
  if options[:dry_run]
1653
- puts "system: #{open_command}"
1875
+ puts Morpheus::Util.open_url_command(link)
1654
1876
  return 0
1655
1877
  end
1656
-
1657
- system(open_command)
1658
-
1659
- return 0
1878
+ return Morpheus::Util.open_url(link)
1660
1879
  rescue RestClient::Exception => e
1661
1880
  print_rest_exception(e, options)
1662
1881
  exit 1
@@ -1761,23 +1980,11 @@ class Morpheus::Cli::Apps
1761
1980
 
1762
1981
  link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/provisioning/apps/#{app['id']}#!wiki"
1763
1982
 
1764
- open_command = nil
1765
- if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
1766
- open_command = "start #{link}"
1767
- elsif RbConfig::CONFIG['host_os'] =~ /darwin/
1768
- open_command = "open #{link}"
1769
- elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
1770
- open_command = "xdg-open #{link}"
1771
- end
1772
-
1773
1983
  if options[:dry_run]
1774
- puts "system: #{open_command}"
1984
+ puts Morpheus::Util.open_url_command(link)
1775
1985
  return 0
1776
1986
  end
1777
-
1778
- system(open_command)
1779
-
1780
- return 0
1987
+ return Morpheus::Util.open_url(link)
1781
1988
  rescue RestClient::Exception => e
1782
1989
  print_rest_exception(e, options)
1783
1990
  exit 1
@@ -1900,39 +2107,13 @@ class Morpheus::Cli::Apps
1900
2107
  # list
1901
2108
  # end
1902
2109
 
1903
- def find_app_by_id(id)
1904
- app_results = @apps_interface.get(id.to_i)
1905
- if app_results['app'].empty?
1906
- print_red_alert "App not found by id #{id}"
1907
- exit 1
1908
- end
1909
- return app_results['app']
1910
- end
1911
-
1912
- def find_app_by_name(name)
1913
- app_results = @apps_interface.list({name: name})
1914
- if app_results['apps'].empty?
1915
- print_red_alert "App not found by name #{name}"
1916
- exit 1
1917
- end
1918
- return app_results['apps'][0]
1919
- end
1920
-
1921
- def find_app_by_name_or_id(val)
1922
- if val.to_s =~ /\A\d{1,}\Z/
1923
- return find_app_by_id(val)
1924
- else
1925
- return find_app_by_name(val)
1926
- end
1927
- end
1928
-
1929
2110
  def print_apps_table(apps, options={})
1930
2111
 
1931
2112
  table_color = options[:color] || cyan
1932
2113
  rows = apps.collect do |app|
1933
2114
  tiers_str = format_app_tiers(app)
1934
- instances_str = (app['instanceCount'].to_i == 1) ? "1 Instance" : "#{app['instanceCount']} Instances"
1935
- containers_str = (app['containerCount'].to_i == 1) ? "1 Container" : "#{app['containerCount']} Containers"
2115
+ instances_str = (app['instanceCount'].to_i == 1) ? "1" : "#{app['instanceCount']}"
2116
+ containers_str = (app['containerCount'].to_i == 1) ? "1" : "#{app['containerCount']}"
1936
2117
  stats = app['stats']
1937
2118
  # app_stats = app['appStats']
1938
2119
  cpu_usage_str = !stats ? "" : generate_usage_bar((stats['cpuUsage'] || stats['cpuUsagePeak']).to_f, 100, {max_bars: 10})
@@ -1949,34 +2130,44 @@ class Morpheus::Cli::Apps
1949
2130
  {
1950
2131
  id: app['id'],
1951
2132
  name: app['name'],
2133
+ description: app['description'],
2134
+ blueprint: app['blueprint'] ? app['blueprint']['name'] : '',
2135
+ type: app['type'] ? format_blueprint_type(app['type']) : (format_blueprint_type(app['blueprint'] ? app['blueprint']['type'] : nil)),
1952
2136
  group: app['group'] ? app['group']['name'] : app['siteId'],
1953
2137
  environment: app['appContext'],
1954
2138
  tiers: tiers_str,
1955
2139
  instances: instances_str,
1956
2140
  containers: containers_str,
1957
- account: app['account'] ? app['account']['name'] : nil,
2141
+ owner: app['owner'] ? app['owner']['username'] : '',
2142
+ tenant: app['account'] ? app['account']['name'] : nil,
1958
2143
  status: format_app_status(app, table_color),
1959
2144
  cpu: cpu_usage_str + cyan,
1960
2145
  memory: memory_usage_str + table_color,
1961
- storage: storage_usage_str + table_color
1962
- #dateCreated: format_local_dt(app['dateCreated'])
2146
+ storage: storage_usage_str + table_color,
2147
+ created: format_local_dt(app['dateCreated']),
2148
+ updated: format_local_dt(app['lastUpdated'])
1963
2149
  }
1964
2150
  end
1965
2151
 
1966
2152
  columns = [
1967
2153
  :id,
1968
2154
  :name,
2155
+ # :description,
2156
+ :type,
2157
+ :blueprint,
1969
2158
  :group,
1970
2159
  :environment,
2160
+ :status,
1971
2161
  :tiers,
1972
2162
  :instances,
1973
2163
  :containers,
1974
- #:account,
1975
- :status,
1976
- #{:dateCreated => {:display_name => "Date Created"} },
1977
2164
  {:cpu => {:display_name => "MAX CPU"} },
1978
2165
  :memory,
1979
- :storage
2166
+ :storage,
2167
+ :owner,
2168
+ #:tenant,
2169
+ :created,
2170
+ :updated
1980
2171
  ]
1981
2172
 
1982
2173
  # custom pretty table columns ...