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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api.rb +1 -1
- data/lib/morpheus/api/activity_interface.rb +9 -0
- data/lib/morpheus/api/api_client.rb +83 -27
- data/lib/morpheus/api/apps_interface.rb +21 -0
- data/lib/morpheus/api/dashboard_interface.rb +5 -21
- data/lib/morpheus/api/instances_interface.rb +3 -10
- data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
- data/lib/morpheus/api/invoices_interface.rb +7 -12
- data/lib/morpheus/api/library_layouts_interface.rb +8 -0
- data/lib/morpheus/api/ping_interface.rb +20 -0
- data/lib/morpheus/api/projects_interface.rb +33 -0
- data/lib/morpheus/api/setup_interface.rb +19 -36
- data/lib/morpheus/api/user_settings_interface.rb +0 -6
- data/lib/morpheus/api/whoami_interface.rb +4 -8
- data/lib/morpheus/benchmarking.rb +16 -26
- data/lib/morpheus/cli.rb +10 -5
- data/lib/morpheus/cli/access_token_command.rb +5 -8
- data/lib/morpheus/cli/activity_command.rb +146 -0
- data/lib/morpheus/cli/apps.rb +312 -121
- data/lib/morpheus/cli/archives_command.rb +1 -1
- data/lib/morpheus/cli/auth_command.rb +4 -11
- data/lib/morpheus/cli/blueprints_command.rb +196 -137
- data/lib/morpheus/cli/change_password_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +225 -72
- data/lib/morpheus/cli/cli_registry.rb +2 -2
- data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +5 -20
- data/lib/morpheus/cli/clusters.rb +4 -28
- data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
- data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
- data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
- data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
- data/lib/morpheus/cli/containers_command.rb +3 -3
- data/lib/morpheus/cli/credentials.rb +13 -16
- data/lib/morpheus/cli/error_handler.rb +18 -12
- data/lib/morpheus/cli/errors.rb +45 -0
- data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
- data/lib/morpheus/cli/execution_request_command.rb +4 -4
- data/lib/morpheus/cli/groups.rb +84 -132
- data/lib/morpheus/cli/hosts.rb +6 -16
- data/lib/morpheus/cli/instances.rb +100 -183
- data/lib/morpheus/cli/invoices_command.rb +505 -71
- data/lib/morpheus/cli/library_layouts_command.rb +254 -166
- data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
- data/lib/morpheus/cli/library_option_types_command.rb +0 -96
- data/lib/morpheus/cli/license.rb +3 -0
- data/lib/morpheus/cli/login.rb +17 -37
- data/lib/morpheus/cli/logout.rb +9 -5
- data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
- data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
- data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
- data/lib/morpheus/cli/network_groups_command.rb +8 -2
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/ping.rb +252 -0
- data/lib/morpheus/cli/price_sets_command.rb +16 -27
- data/lib/morpheus/cli/prices_command.rb +34 -27
- data/lib/morpheus/cli/processes_command.rb +81 -7
- data/lib/morpheus/cli/projects_command.rb +607 -0
- data/lib/morpheus/cli/recent_activity_command.rb +87 -65
- data/lib/morpheus/cli/remote.rb +965 -974
- data/lib/morpheus/cli/reports_command.rb +3 -15
- data/lib/morpheus/cli/roles.rb +8 -31
- data/lib/morpheus/cli/service_plans_command.rb +25 -31
- data/lib/morpheus/cli/setup.rb +392 -0
- data/lib/morpheus/cli/shell.rb +144 -56
- data/lib/morpheus/cli/subnets_command.rb +71 -11
- data/lib/morpheus/cli/tasks.rb +3 -3
- data/lib/morpheus/cli/user_sources_command.rb +4 -4
- data/lib/morpheus/cli/users.rb +135 -109
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
- data/lib/morpheus/cli/whoami.rb +90 -129
- data/lib/morpheus/cli/wiki_command.rb +2 -14
- data/lib/morpheus/ext/rest_client.rb +36 -0
- data/lib/morpheus/formatters.rb +42 -5
- data/lib/morpheus/rest_client.rb +0 -10
- data/lib/morpheus/terminal.rb +41 -1
- data/lib/morpheus/util.rb +24 -0
- metadata +16 -3
- 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
|
-
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
data/lib/morpheus/cli.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require 'morpheus/cli/version'
|
|
2
|
-
require 'morpheus/cli/
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
data/lib/morpheus/cli/apps.rb
CHANGED
|
@@ -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( '
|
|
58
|
-
options[:
|
|
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[:
|
|
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
|
-
|
|
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[:
|
|
81
|
-
created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:
|
|
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'] =
|
|
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( '--
|
|
129
|
-
options[:
|
|
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[:
|
|
144
|
-
created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
if
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
if
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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
|
-
|
|
818
|
-
#
|
|
819
|
-
|
|
820
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
1935
|
-
containers_str = (app['containerCount'].to_i == 1) ? "1
|
|
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
|
-
|
|
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
|
-
|
|
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 ...
|