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
|
@@ -176,7 +176,7 @@ class Morpheus::Cli::ReportsCommand
|
|
|
176
176
|
"ID" => lambda {|it| it['id'] },
|
|
177
177
|
"SECTION" => lambda {|it| it['section'] },
|
|
178
178
|
"DATA" => lambda {|it| truncate_string(it['data'], data_width) }
|
|
179
|
-
}, options.merge({:
|
|
179
|
+
}, options.merge({:wrap => true}))
|
|
180
180
|
|
|
181
181
|
else
|
|
182
182
|
print yellow, "No report data found.", reset, "\n"
|
|
@@ -338,23 +338,11 @@ class Morpheus::Cli::ReportsCommand
|
|
|
338
338
|
|
|
339
339
|
link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/operations/reports/#{report_result['type']['code']}/reportResults/#{report_result['id']}"
|
|
340
340
|
|
|
341
|
-
open_command = nil
|
|
342
|
-
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
|
343
|
-
open_command = "start #{link}"
|
|
344
|
-
elsif RbConfig::CONFIG['host_os'] =~ /darwin/
|
|
345
|
-
open_command = "open #{link}"
|
|
346
|
-
elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
|
|
347
|
-
open_command = "xdg-open #{link}"
|
|
348
|
-
end
|
|
349
|
-
|
|
350
341
|
if options[:dry_run]
|
|
351
|
-
puts
|
|
342
|
+
puts Morpheus::Util.open_url_command(link)
|
|
352
343
|
return 0
|
|
353
344
|
end
|
|
354
|
-
|
|
355
|
-
system(open_command)
|
|
356
|
-
|
|
357
|
-
return 0
|
|
345
|
+
return Morpheus::Util.open_url(link)
|
|
358
346
|
rescue RestClient::Exception => e
|
|
359
347
|
print_rest_exception(e, options)
|
|
360
348
|
exit 1
|
data/lib/morpheus/cli/roles.rb
CHANGED
|
@@ -94,7 +94,7 @@ class Morpheus::Cli::Roles
|
|
|
94
94
|
opts.on('-p','--permissions', "Display Permissions") do |val|
|
|
95
95
|
options[:include_feature_access] = true
|
|
96
96
|
end
|
|
97
|
-
opts.on('-f','--feature-access', "Display
|
|
97
|
+
opts.on('-f','--feature-access', "Display Permissions [deprecated]") do |val|
|
|
98
98
|
options[:include_feature_access] = true
|
|
99
99
|
end
|
|
100
100
|
opts.add_hidden_option('--feature-access')
|
|
@@ -200,7 +200,7 @@ class Morpheus::Cli::Roles
|
|
|
200
200
|
{
|
|
201
201
|
code: it['code'],
|
|
202
202
|
name: it['name'],
|
|
203
|
-
access:
|
|
203
|
+
access: format_access_string(it['access']),
|
|
204
204
|
}
|
|
205
205
|
end
|
|
206
206
|
if options[:sort]
|
|
@@ -219,13 +219,6 @@ class Morpheus::Cli::Roles
|
|
|
219
219
|
end
|
|
220
220
|
|
|
221
221
|
print_h2 "Global Access", options
|
|
222
|
-
# role_access_rows = [
|
|
223
|
-
# {name: "Groups", access: get_access_string(json_response['globalSiteAccess']) },
|
|
224
|
-
# {name: "Clouds", access: get_access_string(json_response['globalZoneAccess']) },
|
|
225
|
-
# {name: "Instance Types", access: get_access_string(json_response['globalInstanceTypeAccess']) },
|
|
226
|
-
# {name: "Blueprints", access: get_access_string(json_response['globalAppTemplateAccess'] || json_response['globalBlueprintAccess']) }
|
|
227
|
-
# ]
|
|
228
|
-
# puts as_pretty_table(role_access_rows, [:name, :access], options)
|
|
229
222
|
puts as_pretty_table([json_response], [
|
|
230
223
|
{"Groups" => lambda {|it| get_access_string(it['globalSiteAccess']) } },
|
|
231
224
|
{"Clouds" => lambda {|it| get_access_string(it['globalZoneAccess']) } },
|
|
@@ -241,7 +234,7 @@ class Morpheus::Cli::Roles
|
|
|
241
234
|
rows = json_response['sites'].collect do |it|
|
|
242
235
|
{
|
|
243
236
|
name: it['name'],
|
|
244
|
-
access:
|
|
237
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
|
245
238
|
}
|
|
246
239
|
end
|
|
247
240
|
print as_pretty_table(rows, [:name, :access], options)
|
|
@@ -262,7 +255,7 @@ class Morpheus::Cli::Roles
|
|
|
262
255
|
rows = json_response['zones'].collect do |it|
|
|
263
256
|
{
|
|
264
257
|
name: it['name'],
|
|
265
|
-
access:
|
|
258
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
|
266
259
|
}
|
|
267
260
|
end
|
|
268
261
|
print as_pretty_table(rows, [:name, :access], options)
|
|
@@ -283,7 +276,7 @@ class Morpheus::Cli::Roles
|
|
|
283
276
|
rows = json_response['instanceTypePermissions'].collect do |it|
|
|
284
277
|
{
|
|
285
278
|
name: it['name'],
|
|
286
|
-
access:
|
|
279
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
|
287
280
|
}
|
|
288
281
|
end
|
|
289
282
|
print as_pretty_table(rows, [:name, :access], options)
|
|
@@ -306,7 +299,7 @@ class Morpheus::Cli::Roles
|
|
|
306
299
|
rows = blueprint_permissions.collect do |it|
|
|
307
300
|
{
|
|
308
301
|
name: it['name'],
|
|
309
|
-
access:
|
|
302
|
+
access: format_access_string(it['access'], ["none","read","full"]),
|
|
310
303
|
}
|
|
311
304
|
end
|
|
312
305
|
print as_pretty_table(rows, [:name, :access], options)
|
|
@@ -393,7 +386,7 @@ class Morpheus::Cli::Roles
|
|
|
393
386
|
{
|
|
394
387
|
code: it['code'],
|
|
395
388
|
name: it['name'],
|
|
396
|
-
access:
|
|
389
|
+
access: format_access_string(it['access']),
|
|
397
390
|
}
|
|
398
391
|
end
|
|
399
392
|
if options[:sort]
|
|
@@ -1306,15 +1299,7 @@ class Morpheus::Cli::Roles
|
|
|
1306
1299
|
end
|
|
1307
1300
|
|
|
1308
1301
|
private
|
|
1309
|
-
|
|
1310
|
-
# val ||= 'none'
|
|
1311
|
-
# if val == 'none'
|
|
1312
|
-
# "#{white}#{val.to_s.capitalize}#{cyan}"
|
|
1313
|
-
# else
|
|
1314
|
-
# "#{green}#{val.to_s.capitalize}#{cyan}"
|
|
1315
|
-
# end
|
|
1316
|
-
# end
|
|
1317
|
-
|
|
1302
|
+
|
|
1318
1303
|
def add_role_option_types
|
|
1319
1304
|
[
|
|
1320
1305
|
{'fieldName' => 'authority', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
|
@@ -1343,14 +1328,6 @@ class Morpheus::Cli::Roles
|
|
|
1343
1328
|
end
|
|
1344
1329
|
end
|
|
1345
1330
|
|
|
1346
|
-
def find_instance_type_by_name(name)
|
|
1347
|
-
results = @instance_types_interface.list({name: name})
|
|
1348
|
-
if results['instanceTypes'].empty?
|
|
1349
|
-
print_red_alert "Instance Type not found by name #{name}"
|
|
1350
|
-
return nil
|
|
1351
|
-
end
|
|
1352
|
-
return results['instanceTypes'][0]
|
|
1353
|
-
end
|
|
1354
1331
|
|
|
1355
1332
|
def load_whoami
|
|
1356
1333
|
whoami_response = @whoami_interface.get()
|
|
@@ -34,45 +34,39 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
34
34
|
opts.on('-i', '--include-inactive [on|off]', String, "Can be used to enable / disable inactive filter. Default is on") do |val|
|
|
35
35
|
params['includeInactive'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
build_standard_list_options(opts, options)
|
|
38
38
|
opts.footer = "List service plans."
|
|
39
39
|
end
|
|
40
40
|
optparse.parse!(args)
|
|
41
|
+
#verify_args!(args:args, optparse:optparse, count:0)
|
|
41
42
|
connect(options)
|
|
42
|
-
if args.count != 0
|
|
43
|
-
raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args}\n#{optparse}"
|
|
44
|
-
return 1
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
begin
|
|
48
|
-
params.merge!(parse_list_options(options))
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
|
|
45
|
+
params.merge!(parse_list_options(options))
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
exit 1
|
|
56
|
-
end
|
|
57
|
-
params['provisionTypeId'] = type['id']
|
|
58
|
-
end
|
|
47
|
+
if !options[:provisionType].nil?
|
|
48
|
+
type = find_provision_type(options[:provisionType])
|
|
59
49
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return
|
|
50
|
+
if type.nil?
|
|
51
|
+
print_red_alert "Provision type #{options[:provisionType]} not found"
|
|
52
|
+
exit 1
|
|
64
53
|
end
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
render_result = render_with_format(json_response, options, 'servicePlans')
|
|
68
|
-
return 0 if render_result
|
|
54
|
+
params['provisionTypeId'] = type['id']
|
|
55
|
+
end
|
|
69
56
|
|
|
57
|
+
@service_plans_interface.setopts(options)
|
|
58
|
+
if options[:dry_run]
|
|
59
|
+
print_dry_run @service_plans_interface.dry.list(params)
|
|
60
|
+
return
|
|
61
|
+
end
|
|
62
|
+
json_response = @service_plans_interface.list(params)
|
|
63
|
+
plans = json_response['servicePlans']
|
|
64
|
+
render_response(json_response, options, 'servicePlans') do
|
|
70
65
|
title = "Morpheus Service Plans"
|
|
71
66
|
subtitles = []
|
|
72
67
|
subtitles += parse_list_subtitles(options)
|
|
73
68
|
print_h1 title, subtitles
|
|
74
69
|
|
|
75
|
-
plans = json_response['servicePlans']
|
|
76
70
|
if plans.empty?
|
|
77
71
|
print cyan,"No service plans found.",reset,"\n"
|
|
78
72
|
else
|
|
@@ -91,18 +85,18 @@ class Morpheus::Cli::ServicePlanCommand
|
|
|
91
85
|
}
|
|
92
86
|
end
|
|
93
87
|
columns = [
|
|
94
|
-
:id, :name, :type, :active, :cores, :memory, :clouds, :visibility, :tenants, :price_sets
|
|
88
|
+
:id, :name, :type, :active, :cores, :memory, :clouds, :visibility, :tenants, {"PRICE SETS" => :price_sets}
|
|
95
89
|
]
|
|
96
90
|
columns.delete(:active) if !params['includeInactive']
|
|
97
|
-
|
|
98
91
|
print as_pretty_table(rows, columns, options)
|
|
99
92
|
print_results_pagination(json_response)
|
|
100
93
|
end
|
|
101
94
|
print reset,"\n"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
end
|
|
96
|
+
if plans.empty?
|
|
97
|
+
return 1, "0 plans found"
|
|
98
|
+
else
|
|
99
|
+
return 0, nil
|
|
106
100
|
end
|
|
107
101
|
end
|
|
108
102
|
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
# The morpheus setup command provides interaction with /api/setup
|
|
4
|
+
# This is initializing a fresh remote appliance.
|
|
5
|
+
# and checking the remote status and version.
|
|
6
|
+
class Morpheus::Cli::Setup
|
|
7
|
+
include Morpheus::Cli::CliCommand
|
|
8
|
+
include Morpheus::Cli::RemoteHelper
|
|
9
|
+
|
|
10
|
+
set_command_name :setup
|
|
11
|
+
|
|
12
|
+
register_subcommands :init
|
|
13
|
+
|
|
14
|
+
# no authorization needed
|
|
15
|
+
def connect(options={})
|
|
16
|
+
@api_client = establish_remote_appliance_connection({:no_authorization => true, :skip_login => true}.merge(options))
|
|
17
|
+
@setup_interface = @api_client.setup
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def handle(args)
|
|
21
|
+
#handle_subcommand(args)
|
|
22
|
+
init(args)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# this is a wizard that walks through the /api/setup controller
|
|
26
|
+
# it only needs to be used once to initialize a new appliance
|
|
27
|
+
# def setup(args)
|
|
28
|
+
def init(args)
|
|
29
|
+
params, payload = {}, {}
|
|
30
|
+
options = {}
|
|
31
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
|
32
|
+
#opts.banner = subcommand_usage()
|
|
33
|
+
opts.banner = usage
|
|
34
|
+
build_standard_add_options(opts, options, [:quiet, :auto_confirm])
|
|
35
|
+
opts.on('--hubmode MODE','--hubmode MODE', "Choose an option for hub registration possible values are login, register, skip.") do |val|
|
|
36
|
+
options[:hubmode] = val.to_s.downcase
|
|
37
|
+
end
|
|
38
|
+
opts.on('--force','--force', "Force setup, make api request even if setup is unavailable.") do
|
|
39
|
+
options[:force] = true
|
|
40
|
+
end
|
|
41
|
+
# todo: need all the other options here hub-username/password, account-name, username, password, email, etc.
|
|
42
|
+
opts.footer = <<-EOT
|
|
43
|
+
Setup a fresh remote appliance, initializing it.
|
|
44
|
+
First, this checks if setup is available, and returns an error if not.
|
|
45
|
+
Then it prompts to create the master tenant and admin user.
|
|
46
|
+
If Morpheus Hub registration is enabled, you may login or register to retrieve a license key,
|
|
47
|
+
or you can pass `--hubmode skip`.
|
|
48
|
+
This is only available on a new, freshly installed remote appliance,
|
|
49
|
+
and it may only be executed successfully one time.
|
|
50
|
+
EOT
|
|
51
|
+
end
|
|
52
|
+
optparse.parse!(args)
|
|
53
|
+
verify_args!(args:args, count:0, optparse:optparse)
|
|
54
|
+
connect(options)
|
|
55
|
+
exit_code, err = 0, nil
|
|
56
|
+
# construct payload
|
|
57
|
+
if options[:payload]
|
|
58
|
+
payload = options[:payload]
|
|
59
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
60
|
+
else
|
|
61
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
62
|
+
|
|
63
|
+
# @setup_interface = Morpheus::SetupInterface.new({url:@appliance_url,access_token:@access_token})
|
|
64
|
+
appliance_status_json = nil
|
|
65
|
+
begin
|
|
66
|
+
appliance_status_json = @setup_interface.get()
|
|
67
|
+
rescue RestClient::Exception => e
|
|
68
|
+
# pre 4.2.1 api would return HTTP 400 here, but with setupNeeded=false
|
|
69
|
+
# so fallback to the old /api/setup/check
|
|
70
|
+
# this could be in the interface itself..
|
|
71
|
+
if e.response.code == 400
|
|
72
|
+
Morpheus::Logging::DarkPrinter.puts "HTTP 400 from /api/setup, falling back to older /api/setup/check" if Morpheus::Logging.debug?
|
|
73
|
+
begin
|
|
74
|
+
appliance_status_json = @setup_interface.check()
|
|
75
|
+
rescue RestClient::Exception => e2
|
|
76
|
+
# err = e2.message || "Bad Request"
|
|
77
|
+
begin
|
|
78
|
+
appliance_status_json = JSON.parse(e2.response.to_s)
|
|
79
|
+
rescue TypeError, JSON::ParserError => ex
|
|
80
|
+
#puts "Failed to parse error response as json: #{ex}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# my_terminal.execute("setup needed?")
|
|
87
|
+
# theres a bug here with --remote-url :status == "unknown"
|
|
88
|
+
# but hey, we got json back, so set status to "ready"
|
|
89
|
+
remote_status_string = format_appliance_status(@remote_appliance, cyan)
|
|
90
|
+
if appliance_status_json && appliance_status_json['setupNeeded'] == true
|
|
91
|
+
# ok, setupNeeded
|
|
92
|
+
# print_error cyan,"Setup is needed, status is #{remote_status_string}",reset,"\n"
|
|
93
|
+
else
|
|
94
|
+
if options[:force] != true
|
|
95
|
+
print_error cyan,"Setup unavailable, status is #{remote_status_string}",reset,"\n"
|
|
96
|
+
#print_error red, "#{appliance_status_json['msg']}\n", reset
|
|
97
|
+
return 1, "already setup"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# retrieved hub.enabled and hub.url
|
|
102
|
+
hub_settings = appliance_status_json['hubSettings'] || appliance_status_json['hub'] || {}
|
|
103
|
+
|
|
104
|
+
# store login/registration info in here, for prompt default values
|
|
105
|
+
hub_info = nil
|
|
106
|
+
print cyan
|
|
107
|
+
print_h2 "Remote Setup | #{display_appliance(@appliance_name, @appliance_url)}"
|
|
108
|
+
|
|
109
|
+
print cyan
|
|
110
|
+
puts "It looks like you are the first one here, so let's begin."
|
|
111
|
+
print reset, "\n"
|
|
112
|
+
# print "\n"
|
|
113
|
+
unless Morpheus::Cli::OptionTypes.confirm("Would you like to setup and initialize the remote appliance now?", options)
|
|
114
|
+
return 9, "aborted command"
|
|
115
|
+
end
|
|
116
|
+
print "\n"
|
|
117
|
+
hubmode = nil
|
|
118
|
+
hub_init_payload = nil # gets included as payload for hub scoped like hub.email
|
|
119
|
+
if hub_settings['enabled']
|
|
120
|
+
|
|
121
|
+
# Hub Registration
|
|
122
|
+
hub_action_dropdown = [
|
|
123
|
+
{'name' => 'Login to existing hub account', 'value' => 'login', 'isDefault' => true},
|
|
124
|
+
{'name' => 'Register a new hub account', 'value' => 'register'},
|
|
125
|
+
{'name' => 'Skip this step and manually install a license later.', 'value' => 'skip'},
|
|
126
|
+
{'name' => 'Abort', 'value' => 'abort'}
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
print cyan
|
|
131
|
+
puts "Morpheus Hub registration is enabled for your appliance."
|
|
132
|
+
puts "This step will connect to the Morpheus Hub at #{hub_settings['url']}"
|
|
133
|
+
puts "This is done to retrieve and install the license key for your appliance."
|
|
134
|
+
puts "You have several options for how to proceed:"
|
|
135
|
+
hub_action_dropdown.each_with_index do |hub_action, idx|
|
|
136
|
+
puts "#{idx+1}. #{hub_action['name']} [#{hub_action['value']}]"
|
|
137
|
+
end
|
|
138
|
+
print "\n", reset
|
|
139
|
+
|
|
140
|
+
while hubmode == nil do
|
|
141
|
+
|
|
142
|
+
options[:options]['hubmode'] = options[:hubmode] if options.key?(:hubmode)
|
|
143
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'hubmode', 'fieldLabel' => 'Choose Hub Mode', 'type' => 'select', 'selectOptions' => hub_action_dropdown, 'required' => true, 'defaultValue' => 'login'}], options[:options])
|
|
144
|
+
hubmode = v_prompt['hubmode']
|
|
145
|
+
|
|
146
|
+
if hubmode == 'login'
|
|
147
|
+
|
|
148
|
+
# print cyan
|
|
149
|
+
# puts "MORPHEUS HUB #{hub_settings['url']}"
|
|
150
|
+
# puts "The Command Center for DevOps"
|
|
151
|
+
# print reset
|
|
152
|
+
|
|
153
|
+
# Hub Login
|
|
154
|
+
print_h2 "Morpheus Hub Login @ #{hub_settings['url']}", options
|
|
155
|
+
hub_login_option_types = [
|
|
156
|
+
{'fieldContext' => 'hub', 'fieldName' => 'email', 'fieldLabel' => 'Email', 'type' => 'text', 'required' => true, 'description' => 'Email Address of existing Morpheus Hub user to link with.'},
|
|
157
|
+
{'fieldContext' => 'hub', 'fieldName' => 'password', 'fieldLabel' => 'Password', 'type' => 'password', 'required' => true, 'description' => 'Password of existing Morpheus Hub user.'},
|
|
158
|
+
]
|
|
159
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(hub_login_option_types, options[:options])
|
|
160
|
+
hub_login_payload = v_prompt['hub']
|
|
161
|
+
hub_login_response = nil
|
|
162
|
+
begin
|
|
163
|
+
hub_login_response = @setup_interface.hub_login(hub_login_payload)
|
|
164
|
+
hub_init_payload = hub_login_payload
|
|
165
|
+
hub_info = {'email' => hub_login_payload['email'], 'password' => hub_login_payload['password'] }
|
|
166
|
+
hub_info.deep_merge!(hub_login_response['data']['info']) if (hub_login_response['data'] && hub_login_response['data']['info'])
|
|
167
|
+
hub_info.deep_merge!(hub_login_response['hub']) if hub_login_response['hub'].is_a?(Hash)
|
|
168
|
+
print_green_success "Logged into Morpheus Hub as #{hub_info['email']}"
|
|
169
|
+
rescue RestClient::Exception => e
|
|
170
|
+
hub_login_response = parse_rest_exception(e)
|
|
171
|
+
error_msg = hub_login_response["msg"] || "Hub login failed."
|
|
172
|
+
print_error red,error_msg,reset,"\n"
|
|
173
|
+
hubmode = nil
|
|
174
|
+
#print_rest_exception(e, options)
|
|
175
|
+
#exit 1
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# DEBUG
|
|
179
|
+
if options[:debug] && hub_login_response
|
|
180
|
+
print_h2 "JSON response for hub login"
|
|
181
|
+
Morpheus::Logging::DarkPrinter.puts as_json(hub_login_response)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
elsif hubmode == 'register'
|
|
185
|
+
# Hub Registration
|
|
186
|
+
print_h2 "Morpheus Hub Registration", options
|
|
187
|
+
hub_register_option_types = [
|
|
188
|
+
{'fieldContext' => 'hub', 'fieldName' => 'companyName', 'fieldLabel' => 'Company Name', 'type' => 'text', 'required' => true, 'description' => 'Company Name of new Morpheus Hub account to be created.'},
|
|
189
|
+
{'fieldContext' => 'hub', 'fieldName' => 'firstName', 'fieldLabel' => 'First Name', 'type' => 'text', 'required' => true, 'description' => 'First Name of new Morpheus Hub user.'},
|
|
190
|
+
{'fieldContext' => 'hub', 'fieldName' => 'lastName', 'fieldLabel' => 'Last Name', 'type' => 'text', 'required' => true, 'description' => 'Last Name of new Morpheus Hub user.'},
|
|
191
|
+
{'fieldContext' => 'hub', 'fieldName' => 'email', 'fieldLabel' => 'Email', 'type' => 'text', 'required' => true, 'description' => 'Email Address of new Morpheus Hub user.'}
|
|
192
|
+
]
|
|
193
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(hub_register_option_types, options[:options])
|
|
194
|
+
hub_register_payload = v_prompt['hub']
|
|
195
|
+
|
|
196
|
+
# Password prompt with re-prompting if no match
|
|
197
|
+
need_password = true
|
|
198
|
+
if options[:no_prompt]
|
|
199
|
+
if options[:options]['hub'] && options[:options]['hub']['password']
|
|
200
|
+
options[:options]['hub']['confirmPassword'] = options[:options]['hub']['password']
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
while need_password do
|
|
204
|
+
password_option_types = [
|
|
205
|
+
{'fieldContext' => 'hub', 'fieldName' => 'password', 'fieldLabel' => 'Create Password', 'type' => 'password', 'required' => true, 'description' => 'Confirm password of new Morpheus Hub user.'},
|
|
206
|
+
{'fieldContext' => 'hub', 'fieldName' => 'confirmPassword', 'fieldLabel' => 'Confirm Password', 'type' => 'password', 'required' => true, 'description' => 'Confirm password of new Morpheus Hub user.'}
|
|
207
|
+
]
|
|
208
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
|
|
209
|
+
if v_prompt['hub']['password'] == v_prompt['hub']['confirmPassword']
|
|
210
|
+
hub_register_payload.deep_merge!(v_prompt['hub'])
|
|
211
|
+
need_password = false
|
|
212
|
+
else
|
|
213
|
+
print_error red, "Password confirmation does not match. Re-enter your new password.", reset, "\n"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
begin
|
|
218
|
+
hub_register_response = @setup_interface.hub_register(hub_register_payload)
|
|
219
|
+
hub_init_payload = hub_register_payload
|
|
220
|
+
hub_info = {'email' => hub_register_payload['email'], 'password' => hub_register_payload['password'] }
|
|
221
|
+
hub_info.deep_merge!(hub_register_payload)
|
|
222
|
+
hub_info.deep_merge!(hub_register_response['data']['info']) if (hub_register_response['data'] && hub_register_response['data']['info'])
|
|
223
|
+
hub_info.deep_merge!(hub_register_response['hub']) if hub_register_response['hub'].is_a?(Hash)
|
|
224
|
+
print_green_success "Registered with Morpheus Hub as #{hub_info['email']}"
|
|
225
|
+
# uh ok so that means the init() request can use login
|
|
226
|
+
# this avoid duplicate email error
|
|
227
|
+
# but it can also just omit hubMode from the init() payload to achieve the same thing.
|
|
228
|
+
# hubmode = nil
|
|
229
|
+
rescue RestClient::Exception => e
|
|
230
|
+
hub_register_response = parse_rest_exception(e)
|
|
231
|
+
error_msg = hub_register_response["msg"] || "Hub Registration failed."
|
|
232
|
+
print_error red,error_msg,reset,"\n"
|
|
233
|
+
hubmode = nil
|
|
234
|
+
#print_rest_exception(e, options)
|
|
235
|
+
#exit 1
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# DEBUG
|
|
239
|
+
if options[:debug] && hub_register_response
|
|
240
|
+
print_h2 "JSON response for hub registration"
|
|
241
|
+
Morpheus::Logging::DarkPrinter.puts as_json(hub_register_response)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
elsif hubmode == 'skip'
|
|
245
|
+
print cyan,"Skipping hub registraton for now...",reset,"\n"
|
|
246
|
+
# puts "You may enter a license key later."
|
|
247
|
+
elsif hubmode == 'abort'
|
|
248
|
+
return 9, "aborted command"
|
|
249
|
+
else
|
|
250
|
+
hubmode = nil
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# ok, we're done with the hub.
|
|
256
|
+
# now build the payload for POST /api/setup/init
|
|
257
|
+
|
|
258
|
+
payload = {}
|
|
259
|
+
# payload.deep_merge!(params)
|
|
260
|
+
|
|
261
|
+
# print cyan
|
|
262
|
+
#print_h1 "Morpheus Appliance Setup", [], options
|
|
263
|
+
#print cyan
|
|
264
|
+
#puts "Initializing remote appliance at URL: #{@appliance_url}"
|
|
265
|
+
|
|
266
|
+
# Master Account
|
|
267
|
+
print_h2 "Create Master Tenant", options
|
|
268
|
+
account_option_types = [
|
|
269
|
+
{'fieldName' => 'accountName', 'fieldLabel' => 'Master Tenant Name', 'type' => 'text', 'required' => true, 'defaultValue' => (hub_info ? hub_info['companyName'] : nil), 'description' => 'A unique name for the Master Tenant (account).'},
|
|
270
|
+
]
|
|
271
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(account_option_types, options[:options])
|
|
272
|
+
payload.merge!(v_prompt)
|
|
273
|
+
|
|
274
|
+
# Master User
|
|
275
|
+
print_h2 "Create Master User", options
|
|
276
|
+
user_option_types = [
|
|
277
|
+
{'fieldName' => 'firstName', 'fieldLabel' => 'First Name', 'type' => 'text', 'required' => false, 'defaultValue' => (hub_info ? hub_info['firstName'] : nil), 'description' => 'First name of the user.'},
|
|
278
|
+
{'fieldName' => 'lastName', 'fieldLabel' => 'Last Name', 'type' => 'text', 'required' => false, 'defaultValue' => (hub_info ? hub_info['lastName'] : nil), 'description' => 'Last name of the user.'},
|
|
279
|
+
{'fieldName' => 'email', 'fieldLabel' => 'Email', 'type' => 'text', 'required' => true, 'defaultValue' => (hub_info ? hub_info['email'] : nil), 'description' => 'A unique email address for the user.'},
|
|
280
|
+
{'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'required' => true, 'description' => 'A unique username for the master user.'}
|
|
281
|
+
]
|
|
282
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(user_option_types, options[:options])
|
|
283
|
+
payload.merge!(v_prompt)
|
|
284
|
+
|
|
285
|
+
# Password prompt with re-prompting if no match
|
|
286
|
+
need_password = true
|
|
287
|
+
if options[:no_prompt]
|
|
288
|
+
options[:options]['confirmPassword'] = payload['password']
|
|
289
|
+
payload['confirmPassword'] = payload['password'] if payload['password']
|
|
290
|
+
end
|
|
291
|
+
while need_password do
|
|
292
|
+
password_option_types = [
|
|
293
|
+
{'fieldName' => 'password', 'fieldLabel' => 'Create Password', 'type' => 'password', 'required' => true, 'description' => 'Create a new password for the user.'},
|
|
294
|
+
{'fieldName' => 'confirmPassword', 'fieldLabel' => 'Confirm Password', 'type' => 'password', 'required' => true, 'description' => 'Confirm the new password for the user.'},
|
|
295
|
+
]
|
|
296
|
+
password_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
|
|
297
|
+
if password_prompt['password'] == password_prompt['confirmPassword']
|
|
298
|
+
payload['password'] = password_prompt['password']
|
|
299
|
+
need_password = false
|
|
300
|
+
else
|
|
301
|
+
print_error red, "Password confirmation does not match. Re-enter your new password.", reset, "\n"
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Appliance Settings
|
|
306
|
+
default_appliance_url = appliance_status_json['applianceUrl']
|
|
307
|
+
if default_appliance_url && default_appliance_url.include?('10.0.2.2:8080') # ignore this default value.
|
|
308
|
+
default_appliance_url = @appliance_url
|
|
309
|
+
end
|
|
310
|
+
default_appliance_name = appliance_status_json['applianceName']
|
|
311
|
+
if default_appliance_name.nil?
|
|
312
|
+
default_appliance_name = @appliance_name
|
|
313
|
+
end
|
|
314
|
+
print_h2 "Appliance Settings", options
|
|
315
|
+
extra_option_types = [
|
|
316
|
+
{'fieldName' => 'applianceName', 'fieldLabel' => 'Appliance Name', 'type' => 'text', 'required' => true, 'defaultValue' => default_appliance_name, 'description' => 'A name for identifying your morpheus appliance.'},
|
|
317
|
+
{'fieldName' => 'applianceUrl', 'fieldLabel' => 'Appliance URL', 'type' => 'text', 'required' => true, 'defaultValue' => default_appliance_url, 'description' => 'Appliance URL. Can be used for integrations and callbacks.'},
|
|
318
|
+
{'fieldName' => 'backups', 'fieldLabel' => 'Enable Backups', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'off', 'description' => 'Backups. Default is off. This means backups are created automatically during provisioning.'},
|
|
319
|
+
{'fieldName' => 'monitoring', 'fieldLabel' => 'Enable Monitoring', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'on', 'description' => 'Enable Monitoring. This means checks are created automatically during provisioning.'},
|
|
320
|
+
{'fieldName' => 'logs', 'fieldLabel' => 'Enable Logs', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'on', 'description' => 'Enable Logs. This means container logs are collected.'}
|
|
321
|
+
]
|
|
322
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(extra_option_types, options[:options])
|
|
323
|
+
payload.merge!(v_prompt)
|
|
324
|
+
|
|
325
|
+
# include hubmode and hub params for login or registration
|
|
326
|
+
# actually we remove hubMode because it has already been setup, probably just now,
|
|
327
|
+
# and the init() request will just used the same creds instead of
|
|
328
|
+
# reauthenticated/registering with the hub
|
|
329
|
+
if hubmode
|
|
330
|
+
payload['hubMode'] = hubmode
|
|
331
|
+
end
|
|
332
|
+
if hub_init_payload
|
|
333
|
+
payload['hub'] = hub_init_payload
|
|
334
|
+
end
|
|
335
|
+
if hubmode == 'register' || hubmode == 'login'
|
|
336
|
+
payload.delete('hubMode')
|
|
337
|
+
payload.delete('hub')
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# ok, make the api request
|
|
343
|
+
@setup_interface.setopts(options)
|
|
344
|
+
if options[:dry_run]
|
|
345
|
+
print_dry_run @setup_interface.dry.init(payload)
|
|
346
|
+
return
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
json_response = @setup_interface.init(payload)
|
|
350
|
+
|
|
351
|
+
render_result = render_with_format(json_response, options)
|
|
352
|
+
return 0 if render_result
|
|
353
|
+
|
|
354
|
+
if options[:json]
|
|
355
|
+
print JSON.pretty_generate(json_response)
|
|
356
|
+
print "\n"
|
|
357
|
+
return
|
|
358
|
+
end
|
|
359
|
+
print "\n"
|
|
360
|
+
print green,"Setup complete for remote #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
|
|
361
|
+
#print cyan, "You may now login with the command `login`.\n"
|
|
362
|
+
# uh, just use Credentials.login(username, password, {save: true})
|
|
363
|
+
cmd_res = Morpheus::Cli::Login.new.login(['--username', payload['username'], '--password', payload['password'], '-q'] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
364
|
+
# print "\n"
|
|
365
|
+
print cyan, "You are now logged in as the System Admin #{payload['username']}.\n"
|
|
366
|
+
print reset
|
|
367
|
+
#print "\n"
|
|
368
|
+
|
|
369
|
+
if hubmode == 'skip'
|
|
370
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to install your License Key now?", options.merge({:default => true}))
|
|
371
|
+
cmd_res = Morpheus::Cli::License.new.apply([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
372
|
+
# license_is_valid = cmd_res != false
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first group now?", options.merge({:default => true}))
|
|
377
|
+
cmd_res = Morpheus::Cli::Groups.new.add(['--use'] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
378
|
+
|
|
379
|
+
#print "\n"
|
|
380
|
+
|
|
381
|
+
# if cmd_res !=
|
|
382
|
+
if ::Morpheus::Cli::OptionTypes::confirm("Would you like to create the first cloud now?", options.merge({:default => true}))
|
|
383
|
+
cmd_res = Morpheus::Cli::Clouds.new.add([] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
384
|
+
#print "\n"
|
|
385
|
+
end
|
|
386
|
+
# end
|
|
387
|
+
end
|
|
388
|
+
print "\n",reset
|
|
389
|
+
return exit_code, err
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
end
|