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
@@ -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 ...