morpheus-cli 4.2.8 → 4.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api.rb +1 -1
  4. data/lib/morpheus/api/activity_interface.rb +9 -0
  5. data/lib/morpheus/api/api_client.rb +83 -27
  6. data/lib/morpheus/api/apps_interface.rb +21 -0
  7. data/lib/morpheus/api/dashboard_interface.rb +5 -21
  8. data/lib/morpheus/api/instances_interface.rb +3 -10
  9. data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
  10. data/lib/morpheus/api/invoices_interface.rb +7 -12
  11. data/lib/morpheus/api/library_layouts_interface.rb +8 -0
  12. data/lib/morpheus/api/ping_interface.rb +20 -0
  13. data/lib/morpheus/api/projects_interface.rb +33 -0
  14. data/lib/morpheus/api/setup_interface.rb +19 -36
  15. data/lib/morpheus/api/user_settings_interface.rb +0 -6
  16. data/lib/morpheus/api/whoami_interface.rb +4 -8
  17. data/lib/morpheus/benchmarking.rb +16 -26
  18. data/lib/morpheus/cli.rb +10 -5
  19. data/lib/morpheus/cli/access_token_command.rb +5 -8
  20. data/lib/morpheus/cli/activity_command.rb +146 -0
  21. data/lib/morpheus/cli/apps.rb +312 -121
  22. data/lib/morpheus/cli/archives_command.rb +1 -1
  23. data/lib/morpheus/cli/auth_command.rb +4 -11
  24. data/lib/morpheus/cli/blueprints_command.rb +196 -137
  25. data/lib/morpheus/cli/change_password_command.rb +1 -1
  26. data/lib/morpheus/cli/cli_command.rb +225 -72
  27. data/lib/morpheus/cli/cli_registry.rb +2 -2
  28. data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
  29. data/lib/morpheus/cli/clouds.rb +5 -20
  30. data/lib/morpheus/cli/clusters.rb +4 -28
  31. data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
  32. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
  33. data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
  34. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
  35. data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
  36. data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
  37. data/lib/morpheus/cli/containers_command.rb +3 -3
  38. data/lib/morpheus/cli/credentials.rb +13 -16
  39. data/lib/morpheus/cli/error_handler.rb +18 -12
  40. data/lib/morpheus/cli/errors.rb +45 -0
  41. data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
  42. data/lib/morpheus/cli/execution_request_command.rb +4 -4
  43. data/lib/morpheus/cli/groups.rb +84 -132
  44. data/lib/morpheus/cli/hosts.rb +6 -16
  45. data/lib/morpheus/cli/instances.rb +100 -183
  46. data/lib/morpheus/cli/invoices_command.rb +505 -71
  47. data/lib/morpheus/cli/library_layouts_command.rb +254 -166
  48. data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
  49. data/lib/morpheus/cli/library_option_types_command.rb +0 -96
  50. data/lib/morpheus/cli/license.rb +3 -0
  51. data/lib/morpheus/cli/login.rb +17 -37
  52. data/lib/morpheus/cli/logout.rb +9 -5
  53. data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
  54. data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
  55. data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
  56. data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
  57. data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
  58. data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
  59. data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
  60. data/lib/morpheus/cli/network_groups_command.rb +8 -2
  61. data/lib/morpheus/cli/option_types.rb +1 -1
  62. data/lib/morpheus/cli/ping.rb +252 -0
  63. data/lib/morpheus/cli/price_sets_command.rb +16 -27
  64. data/lib/morpheus/cli/prices_command.rb +34 -27
  65. data/lib/morpheus/cli/processes_command.rb +81 -7
  66. data/lib/morpheus/cli/projects_command.rb +607 -0
  67. data/lib/morpheus/cli/recent_activity_command.rb +87 -65
  68. data/lib/morpheus/cli/remote.rb +965 -974
  69. data/lib/morpheus/cli/reports_command.rb +3 -15
  70. data/lib/morpheus/cli/roles.rb +8 -31
  71. data/lib/morpheus/cli/service_plans_command.rb +25 -31
  72. data/lib/morpheus/cli/setup.rb +392 -0
  73. data/lib/morpheus/cli/shell.rb +144 -56
  74. data/lib/morpheus/cli/subnets_command.rb +71 -11
  75. data/lib/morpheus/cli/tasks.rb +3 -3
  76. data/lib/morpheus/cli/user_sources_command.rb +4 -4
  77. data/lib/morpheus/cli/users.rb +135 -109
  78. data/lib/morpheus/cli/version.rb +1 -1
  79. data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
  80. data/lib/morpheus/cli/whoami.rb +90 -129
  81. data/lib/morpheus/cli/wiki_command.rb +2 -14
  82. data/lib/morpheus/ext/rest_client.rb +36 -0
  83. data/lib/morpheus/formatters.rb +42 -5
  84. data/lib/morpheus/rest_client.rb +0 -10
  85. data/lib/morpheus/terminal.rb +41 -1
  86. data/lib/morpheus/util.rb +24 -0
  87. metadata +16 -3
  88. data/lib/morpheus/cli/command_error.rb +0 -22
@@ -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({:responsive_table => false}))
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 "system: #{open_command}"
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
@@ -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 Feature Access [deprecated]") do |val|
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: get_access_string(it['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: get_access_string(it['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: get_access_string(it['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: get_access_string(it['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: get_access_string(it['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: get_access_string(it['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
- # def get_access_string(val)
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
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
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
- if !options[:provisionType].nil?
51
- type = find_provision_type(options[:provisionType])
44
+
45
+ params.merge!(parse_list_options(options))
52
46
 
53
- if type.nil?
54
- print_red_alert "Provision type #{options[:provisionType]} not found"
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
- @service_plans_interface.setopts(options)
61
- if options[:dry_run]
62
- print_dry_run @service_plans_interface.dry.list(params)
63
- return
50
+ if type.nil?
51
+ print_red_alert "Provision type #{options[:provisionType]} not found"
52
+ exit 1
64
53
  end
65
- json_response = @service_plans_interface.list(params)
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
- return 0
103
- rescue RestClient::Exception => e
104
- print_rest_exception(e, options)
105
- exit 1
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