morpheus-cli 4.1.14 → 4.2

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +4 -0
  4. data/lib/morpheus/api/library_container_types_interface.rb +1 -1
  5. data/lib/morpheus/api/library_instance_types_interface.rb +7 -7
  6. data/lib/morpheus/api/library_layouts_interface.rb +1 -1
  7. data/lib/morpheus/api/network_routers_interface.rb +101 -0
  8. data/lib/morpheus/api/tasks_interface.rb +12 -14
  9. data/lib/morpheus/cli.rb +1 -0
  10. data/lib/morpheus/cli/apps.rb +15 -12
  11. data/lib/morpheus/cli/cli_command.rb +40 -2
  12. data/lib/morpheus/cli/clusters.rb +13 -7
  13. data/lib/morpheus/cli/cypher_command.rb +5 -2
  14. data/lib/morpheus/cli/hosts.rb +1 -1
  15. data/lib/morpheus/cli/instances.rb +21 -5
  16. data/lib/morpheus/cli/jobs_command.rb +83 -27
  17. data/lib/morpheus/cli/library_cluster_layouts_command.rb +12 -12
  18. data/lib/morpheus/cli/library_container_scripts_command.rb +52 -40
  19. data/lib/morpheus/cli/library_container_types_command.rb +2 -60
  20. data/lib/morpheus/cli/library_instance_types_command.rb +22 -1
  21. data/lib/morpheus/cli/library_layouts_command.rb +65 -65
  22. data/lib/morpheus/cli/library_option_lists_command.rb +72 -59
  23. data/lib/morpheus/cli/library_option_types_command.rb +30 -186
  24. data/lib/morpheus/cli/library_spec_templates_command.rb +39 -64
  25. data/lib/morpheus/cli/mixins/library_helper.rb +213 -0
  26. data/lib/morpheus/cli/mixins/provisioning_helper.rb +89 -37
  27. data/lib/morpheus/cli/mixins/whoami_helper.rb +16 -1
  28. data/lib/morpheus/cli/network_routers_command.rb +1281 -0
  29. data/lib/morpheus/cli/networks_command.rb +164 -72
  30. data/lib/morpheus/cli/option_types.rb +187 -73
  31. data/lib/morpheus/cli/price_sets_command.rb +4 -4
  32. data/lib/morpheus/cli/prices_command.rb +15 -15
  33. data/lib/morpheus/cli/remote.rb +3 -3
  34. data/lib/morpheus/cli/service_plans_command.rb +17 -8
  35. data/lib/morpheus/cli/tasks.rb +437 -169
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/lib/morpheus/formatters.rb +8 -0
  38. metadata +6 -3
@@ -19,7 +19,7 @@ module Morpheus::Cli::WhoamiHelper
19
19
  exit 1
20
20
  end
21
21
  @is_master_account = whoami_response["isMasterAccount"]
22
-
22
+ @user_permissions = whoami_response["permissions"]
23
23
  if whoami_response["appliance"]
24
24
  @appliance_build_verison = whoami_response["appliance"]["buildVersion"]
25
25
  else
@@ -42,4 +42,19 @@ module Morpheus::Cli::WhoamiHelper
42
42
  end
43
43
  @is_master_account
44
44
  end
45
+
46
+ def current_user
47
+ if @current_user.nil?
48
+ load_whoami
49
+ end
50
+ @current_user
51
+ end
52
+
53
+ def current_user_permissions
54
+ if @user_permissions.nil?
55
+ load_whoami
56
+ end
57
+ @user_permissions
58
+ end
59
+
45
60
  end
@@ -0,0 +1,1281 @@
1
+ require 'rest_client'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'morpheus/cli/cli_command'
5
+ require 'morpheus/cli/mixins/infrastructure_helper'
6
+
7
+ class Morpheus::Cli::NetworkRoutersCommand
8
+ include Morpheus::Cli::CliCommand
9
+ include Morpheus::Cli::InfrastructureHelper
10
+ include Morpheus::Cli::ProvisioningHelper
11
+ include Morpheus::Cli::WhoamiHelper
12
+
13
+ set_command_name :'network-routers'
14
+ register_subcommands :list, :get, :firewall, :dhcp, :routes, :types, :type, :add, :update, :remove
15
+ register_subcommands :add_firewall_rule, :remove_firewall_rule
16
+ register_subcommands :add_route, :remove_route
17
+ register_subcommands :update_permissions
18
+
19
+ def initialize()
20
+ end
21
+
22
+ def connect(opts)
23
+ @api_client = establish_remote_appliance_connection(opts)
24
+ @network_routers_interface = @api_client.network_routers
25
+ @clouds_interface = @api_client.clouds
26
+ @options_interface = @api_client.options
27
+ @accounts_interface = @api_client.accounts
28
+ end
29
+
30
+ def handle(args)
31
+ handle_subcommand(args)
32
+ end
33
+
34
+ def list(args)
35
+ options = {}
36
+ params = {}
37
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
38
+ opts.banner = subcommand_usage()
39
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
40
+ opts.footer = "List network routers."
41
+ end
42
+ optparse.parse!(args)
43
+ connect(options)
44
+ begin
45
+ params.merge!(parse_list_options(options))
46
+ @network_routers_interface.setopts(options)
47
+ if options[:dry_run]
48
+ print_dry_run @network_routers_interface.dry.list(params)
49
+ return
50
+ end
51
+ json_response = @network_routers_interface.list(params)
52
+ routers = json_response["networkRouters"]
53
+ if options[:json]
54
+ puts as_json(json_response, options, "networkRouters")
55
+ return 0
56
+ elsif options[:yaml]
57
+ puts as_yaml(json_response, options, "networkRouters")
58
+ return 0
59
+ elsif options[:csv]
60
+ puts records_as_csv(routers, options)
61
+ return 0
62
+ end
63
+ title = "Morpheus Network Routers"
64
+ subtitles = []
65
+ subtitles += parse_list_subtitles(options)
66
+ print_h1 title, subtitles
67
+ if routers.empty?
68
+ print cyan,"No network routers found.",reset,"\n"
69
+ else
70
+ # STATUS NAME ROUTER TYPE SERVICE NETWORKS EXTERNAL IP
71
+ rows = routers.collect {|router|
72
+ row = {
73
+ id: router['id'],
74
+ name: router['name'],
75
+ status: format_router_status(router),
76
+ router_type: (router['type'] || {})['name'],
77
+ group: router['site'] ? router['site']['name'] : 'Shared',
78
+ service: (router['networkServer'] || {})['name'],
79
+ networks: (router['externalNetwork'] || {})['name'],
80
+ external_ip: router['externalIp']
81
+ }
82
+ row
83
+ }
84
+ columns = [:id, :name, :status, :router_type, :group, :service, :networks, :external_ip]
85
+ if options[:include_fields]
86
+ columns = options[:include_fields]
87
+ end
88
+ print cyan
89
+ print as_pretty_table(rows, columns, options)
90
+ print reset
91
+ if json_response['meta']
92
+ print_results_pagination(json_response, {:label => "network routers", :n_label => "network routers"})
93
+ else
94
+ print_results_pagination({'meta'=>{'total'=>rows.size,'size'=>rows.size,'max'=>options[:max] || rows.size,'offset'=>0}}, {:label => "network routers", :n_label => "network routers"})
95
+ end
96
+ end
97
+ print reset,"\n"
98
+ return 0
99
+ rescue RestClient::Exception => e
100
+ print_rest_exception(e, options)
101
+ exit 1
102
+ end
103
+ end
104
+
105
+ def get(args)
106
+ options = {}
107
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
108
+ opts.banner = subcommand_usage("[router]")
109
+ opts.on('--details', "Display details: firewall, DHCP, and routing." ) do
110
+ options[:details] = true
111
+ end
112
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
113
+ opts.footer = "Display network router details." + "\n" +
114
+ "[router] is required. This is the name or id of a network router."
115
+ end
116
+ optparse.parse!(args)
117
+ if args.count < 1
118
+ puts optparse
119
+ return 1
120
+ end
121
+ connect(options)
122
+ id_list = parse_id_list(args)
123
+ return run_command_for_each_arg(id_list) do |arg|
124
+ _get(arg, options)
125
+ end
126
+ end
127
+
128
+ def _get(id, options)
129
+ begin
130
+ @network_routers_interface.setopts(options)
131
+ if options[:dry_run]
132
+ if arg.to_s =~ /\A\d{1,}\Z/
133
+ print_dry_run @network_routers_interface.dry.get(arg.to_i)
134
+ else
135
+ print_dry_run @network_routers_interface.dry.list({name:arg})
136
+ end
137
+ return
138
+ end
139
+ router = find_router(id)
140
+ if router.nil?
141
+ return 1
142
+ end
143
+
144
+ json_response = {'networkRouter' => router}
145
+
146
+ if options[:json]
147
+ puts as_json(json_response, options, "networkRouter")
148
+ return 0
149
+ elsif options[:yaml]
150
+ puts as_yaml(json_response, options, "networkRouter")
151
+ return 0
152
+ elsif options[:csv]
153
+ puts records_as_csv([json_response['networkRouter']], options)
154
+ return 0
155
+ end
156
+
157
+ print_h1 "Network Router Details"
158
+ print cyan
159
+ description_cols = {
160
+ "ID" => lambda {|it| it['id'] },
161
+ "Name" => lambda {|it| it['name'] },
162
+ "Status" => lambda {|it| format_router_status(it)},
163
+ "Type" => lambda {|it| it['type']['name']},
164
+ "Service" => lambda {|it| it['networkServer'] ? it['networkServer']['name'] : nil},
165
+ "Group" => lambda {|it| it['site'] ? it['site']['name'] : 'Shared'},
166
+ # "Integration" => lambda {|it| router_integration_label(it)},
167
+ "Provider ID" => lambda {|it| it['providerId'] || it['externalId']},
168
+ "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
169
+ "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
170
+ }
171
+
172
+ print_description_list(description_cols, router)
173
+
174
+ if (router['interfaces'] || []).count > 0
175
+ rows = router['interfaces'].sort_by{|it| it['networkPosition']}.collect do |it|
176
+ {
177
+ position: it['networkPosition'],
178
+ name: it['name'],
179
+ type: it['interfaceType'],
180
+ network: (it['network'] || {})['name'],
181
+ link: it['externalLink'],
182
+ ip_address: it['ipAddress'],
183
+ subnet: it['cidr'],
184
+ enabled: format_boolean(it['enabled'])
185
+ }
186
+ end
187
+ print_h2 "Interfaces"
188
+ puts as_pretty_table(rows, [:position, :name, :type, :link, :network, :ip_address, :subnet, :enabled])
189
+ end
190
+
191
+ if router['type']['hasFirewall']
192
+ print_h2 "Firewall"
193
+ print cyan
194
+ print_firewall(router, options[:details])
195
+ end
196
+ if router['type']['hasDhcp']
197
+ print_h2 "DHCP"
198
+ print cyan
199
+ print_dhcp(router, options[:details])
200
+ end
201
+ if router['type']['hasRouting'] && options[:details]
202
+ print_h2 "Routes"
203
+ print cyan
204
+ print_routes(router)
205
+ end
206
+ if router['permissions'] && options[:details]
207
+ print_h2 "Tenant Permissions"
208
+ print cyan
209
+ description_cols = {
210
+ "Visibility" => lambda{|it| it['permissions']['visibility']},
211
+ "Tenants" => lambda{|it|
212
+ accounts = (it['permissions']['tenantPermissions'] || {})['accounts'] || []
213
+ accounts.count > 0 ? accounts.join(', ') : ''
214
+ }
215
+ }
216
+ print_description_list(description_cols, router)
217
+ println
218
+ end
219
+ print reset
220
+ rescue RestClient::Exception => e
221
+ print_rest_exception(e, options)
222
+ return 1
223
+ end
224
+ end
225
+
226
+ def add(args)
227
+ options = {:options=>{}}
228
+ params = {}
229
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
230
+ opts.banner = subcommand_usage("[type] [name] [options]")
231
+ opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
232
+ options[:group] = val
233
+ end
234
+ opts.on('-t', '--type VALUE', String, "Name or ID of router type") do |val|
235
+ options[:options]['routerType'] = val
236
+ end
237
+ opts.on('-n', '--name VALUE', String, "Name for this network router") do |val|
238
+ options[:options]['name'] = val
239
+ end
240
+ opts.on('-D', '--description VALUE', String, "Description") do |val|
241
+ options[:options]['description'] = val
242
+ end
243
+ opts.on('-s', '--server VALUE', String, "Network server") do |val|
244
+ options[:network_server] = val
245
+ end
246
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
247
+ options[:cloud] = val
248
+ end
249
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the network router. Default is on") do |val|
250
+ options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
251
+ end
252
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
253
+ opts.footer = "Create a network router."
254
+ end
255
+ optparse.parse!(args)
256
+ connect(options)
257
+ if args.count > 2
258
+ print_error Morpheus::Terminal.angry_prompt
259
+ puts_error "wrong number of arguments, expected 0-2 and got (#{args.count}) #{args.inspect}\n#{optparse}"
260
+ return 1
261
+ end
262
+ if args.count > 0
263
+ options[:options]['routerType'] = args[0]
264
+ end
265
+ if args.count > 1
266
+ params['name'] = args[1]
267
+ end
268
+ begin
269
+ if options[:payload]
270
+ payload = options[:payload]
271
+ else
272
+ router_type = prompt_router_type(options)
273
+ router = {'type' => {'id' => router_type['id']}, 'enabled' => options[:enabled].nil? || options[:enabled] }
274
+
275
+ group_options = available_groups
276
+
277
+ if options[:group]
278
+ group = avail_groups.find {|it| it['name'] == options[:group] || "#{it['value']}" == "#{options[:group]}".downcase}
279
+
280
+ if group.nil?
281
+ print_red_alert "Group #{options[:group]} not found"
282
+ exit 1
283
+ end
284
+ router['site'] = {'id' => group['value']}
285
+ else
286
+ default_group = group_options.find {|it| it['value'] == 'shared'} ? 'shared' : nil
287
+ group_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Group', 'required' => true, 'selectOptions' => group_options, 'defaultValue' => default_group}], options[:options], @api_client, params, nil, true)['group']
288
+ router['site'] = {'id' => group_id}
289
+ end
290
+
291
+ # add router type to be used for option prompts
292
+ params = {'router' => {'site' => router['site']}, 'routerType' => {'id' => router_type['id']}}
293
+
294
+ if router_type['hasNetworkServer']
295
+ if options[:server]
296
+ server = find_network_server(options[:server])
297
+ if server.nil?
298
+ print_red_alert "Network server #{options[:server]} not found"
299
+ exit 1
300
+ end
301
+ else
302
+ server_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkServer', 'type' => 'select', 'fieldLabel' => 'Network Server', 'required' => true, 'optionSource' => 'networkServer'}], options[:options], @api_client, params, nil, true)['networkServer']
303
+ server = {'id' => server_id}
304
+ end
305
+ router['networkServer'] = {'id' => server['id']}
306
+ params['networkServerId'] = server['id']
307
+ else
308
+ # prompt cloud
309
+ if options[:cloud]
310
+ cloud = find_cloud_by_name_or_id(options[:cloud])
311
+ if cloud.nil?
312
+ print_red_alert "Cloud #{options[:cloud]} not found"
313
+ exit 1
314
+ end
315
+ else
316
+ cloud_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zone', 'type' => 'select', 'fieldLabel' => 'Cloud', 'required' => true, 'optionSource' => 'routerTypeCloud'}], options[:options], @api_client, params, nil, true)['zone']
317
+ cloud = {'id' => cloud_id}
318
+ end
319
+ router['zone'] = params['zone'] = {'id' => cloud['id']}
320
+ end
321
+
322
+ # prompt for enabled
323
+ router['enabled'] = options[:enabled].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'description' => 'Enable Router.', 'defaultValue' => true, 'required' => false}], options, @api_client, {})['enabled'] == 'on' : options[:enabled]
324
+
325
+ option_types = router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
326
+
327
+ # prompt options
328
+ option_opts = options[:options].deep_merge!({'config' => options[:options].clone})
329
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, option_opts.merge({:context_map => {'networkRouter' => ''}}), @api_client, params)
330
+ payload = {'networkRouter' => router.deep_merge(option_result)}
331
+ payload['networkRouter']['config'] = option_result['config'] if option_result['config']
332
+ end
333
+
334
+ @network_routers_interface.setopts(options)
335
+ if options[:dry_run]
336
+ print_dry_run @network_routers_interface.dry.create(payload)
337
+ return
338
+ end
339
+
340
+ json_response = @network_routers_interface.create(payload)
341
+
342
+ if options[:json]
343
+ print JSON.pretty_generate(json_response), "\n"
344
+ return
345
+ end
346
+ print_green_success "Added Network Router #{payload['networkRouter']['name']}"
347
+ _get(json_response['id'], options)
348
+ rescue RestClient::Exception => e
349
+ print_rest_exception(e, options)
350
+ exit 1
351
+ end
352
+ end
353
+
354
+ def update(args)
355
+ options = {:options=>{}}
356
+ params = {}
357
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
358
+ opts.banner = subcommand_usage("[router]")
359
+ opts.on('-D', '--description VALUE', String, "Description") do |val|
360
+ params['description'] = val
361
+ end
362
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
363
+ opts.footer = "Update a network router."
364
+ end
365
+ optparse.parse!(args)
366
+ connect(options)
367
+ if args.count != 1
368
+ print_error Morpheus::Terminal.angry_prompt
369
+ puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
370
+ return 1
371
+ end
372
+
373
+ begin
374
+ router = find_router(args[0])
375
+ if router.nil?
376
+ return 1
377
+ end
378
+
379
+ payload = parse_payload(options)
380
+
381
+ if payload.nil?
382
+ if !options[:enabled].nil?
383
+ params['enabled'] = options[:enabled]
384
+ end
385
+
386
+ if options[:options]
387
+ params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) || ['name', 'routerType'].include?(k)})
388
+ end
389
+ payload = {'networkRouter' => params}
390
+ end
391
+
392
+ if payload['networkRouter'].empty?
393
+ print_green_success "Nothing to update"
394
+ return
395
+ end
396
+
397
+ @network_routers_interface.setopts(options)
398
+ if options[:dry_run]
399
+ print_dry_run @network_routers_interface.dry.update(router['id'], payload)
400
+ return
401
+ end
402
+
403
+ json_response = @network_routers_interface.update(router['id'], payload)
404
+
405
+ if options[:json]
406
+ puts as_json(json_response, options)
407
+ elsif !options[:quiet]
408
+ if json_response['success']
409
+ print_green_success "Network router updated"
410
+ _get(router['id'], options)
411
+ else
412
+ print_red_alert "Error updating network router: #{json_response['msg'] || json_response['errors']}"
413
+ end
414
+ end
415
+ return 0
416
+ rescue RestClient::Exception => e
417
+ print_rest_exception(e, options)
418
+ exit 1
419
+ end
420
+ end
421
+
422
+ def remove(args)
423
+ options = {}
424
+ query_params = {}
425
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
426
+ opts.banner = subcommand_usage("[router]")
427
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
428
+ opts.footer = "Delete a network router.\n" +
429
+ "[router] is required. This is the name or id of an existing network router."
430
+ end
431
+ optparse.parse!(args)
432
+ if args.count != 1
433
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
434
+ end
435
+ connect(options)
436
+
437
+ begin
438
+ router = find_router(args[0])
439
+
440
+ return if !router
441
+
442
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the network router '#{router['name']}'?", options)
443
+ return 9, "aborted command"
444
+ end
445
+ @network_routers_interface.setopts(options)
446
+ if options[:dry_run]
447
+ print_dry_run @network_routers_interface.dry.destroy(router['id'], query_params)
448
+ return
449
+ end
450
+ json_response = @network_routers_interface.destroy(router['id'], query_params)
451
+ if options[:json]
452
+ print JSON.pretty_generate(json_response)
453
+ print "\n"
454
+ elsif !options[:quiet]
455
+ print_green_success "Network router #{router['name']} is being removed..."
456
+ end
457
+ rescue RestClient::Exception => e
458
+ print_rest_exception(e, options)
459
+ exit 1
460
+ end
461
+ end
462
+
463
+ def firewall(args)
464
+ options = {}
465
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
466
+ opts.banner = subcommand_usage("[router]")
467
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
468
+ opts.footer = "Display network router firewall details." + "\n" +
469
+ "[router] is required. This is the name or id of a network router."
470
+ end
471
+
472
+ optparse.parse!(args)
473
+ connect(options)
474
+
475
+ if args.count < 1
476
+ puts optparse
477
+ return 1
478
+ end
479
+ _firewall(args[0], options)
480
+ end
481
+
482
+ def _firewall(router_id, options)
483
+ begin
484
+ @network_routers_interface.setopts(options)
485
+ if options[:dry_run]
486
+ if args[0].to_s =~ /\A\d{1,}\Z/
487
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
488
+ else
489
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
490
+ end
491
+ return
492
+ end
493
+ router = find_router(router_id)
494
+ if router.nil?
495
+ return 1
496
+ end
497
+
498
+ json_response = {'networkRouter' => router}
499
+
500
+ if options[:json]
501
+ puts as_json(json_response, options, "networkRouter")
502
+ return 0
503
+ elsif options[:yaml]
504
+ puts as_yaml(json_response, options, "networkRouter")
505
+ return 0
506
+ elsif options[:csv]
507
+ puts records_as_csv([json_response['networkRouter']], options)
508
+ return 0
509
+ end
510
+
511
+ if !options[:rules_only]
512
+ print_h1 "Network Router Firewall Details for: #{router['name']}"
513
+ end
514
+
515
+ print cyan
516
+
517
+ if router['type']['hasFirewall']
518
+ print_firewall(router, true, options[:rules_only])
519
+ else
520
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
521
+ end
522
+ println reset
523
+ rescue RestClient::Exception => e
524
+ print_rest_exception(e, options)
525
+ return 1
526
+ end
527
+ end
528
+
529
+ def add_firewall_rule(args)
530
+ options = {:options=>{}}
531
+ params = {}
532
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
533
+ opts.banner = subcommand_usage("[router] [name]")
534
+ opts.on('-n', '--name VALUE', String, "Name for this firewall rule") do |val|
535
+ params['name'] = val
536
+ end
537
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
538
+ opts.footer = "Create a network router firewall rule."
539
+ end
540
+ optparse.parse!(args)
541
+ connect(options)
542
+ if args.count < 1 || args.count > 2
543
+ print_error Morpheus::Terminal.angry_prompt
544
+ puts_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.inspect}\n#{optparse}"
545
+ return 1
546
+ end
547
+ if args.count > 1
548
+ params['name'] = args[1]
549
+ end
550
+ begin
551
+ router = find_router(args[0])
552
+
553
+ if router.nil?
554
+ return 1
555
+ end
556
+
557
+ if !router['type']['hasFirewall']
558
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
559
+ return 1
560
+ end
561
+
562
+ if options[:payload]
563
+ payload = options[:payload]
564
+ else
565
+ params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Rule Name', 'required' => true}], options[:options], @api_client, params)['name']
566
+
567
+ option_types = router['type']['ruleOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
568
+
569
+ # prompt options
570
+ api_params = {}
571
+ api_params['networkServerId'] = router['networkServer']['id'] if router['networkServer']
572
+ api_params['zoneId'] = router['zone']['id'] if router['networkServer'].nil?
573
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'networkRouter' => ''}}), @api_client, api_params, nil, true)
574
+ payload = {'rule' => params.deep_merge(option_result)}
575
+ end
576
+
577
+ @network_routers_interface.setopts(options)
578
+ if options[:dry_run]
579
+ print_dry_run @network_routers_interface.dry.create_firewall_rule(router['id'], payload)
580
+ return
581
+ end
582
+
583
+ json_response = @network_routers_interface.create_firewall_rule(router['id'], payload)
584
+
585
+ if options[:json]
586
+ print JSON.pretty_generate(json_response), "\n"
587
+ return
588
+ end
589
+ print_green_success "\nAdded Network Router Firewall Rule #{payload['rule']['name']}\n"
590
+ _firewall(router['id'], options.merge({:rules_only => true}))
591
+ rescue RestClient::Exception => e
592
+ print_rest_exception(e, options)
593
+ exit 1
594
+ end
595
+ end
596
+
597
+ def remove_firewall_rule(args)
598
+ options = {}
599
+ query_params = {}
600
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
601
+ opts.banner = subcommand_usage("[router] [rule]")
602
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
603
+ opts.footer = "Delete a network router firewall rule.\n" +
604
+ "[router] is required. This is the name or id of an existing network router."
605
+ "[rule] is required. This is the name or id of an existing network router firewall rule."
606
+ end
607
+ optparse.parse!(args)
608
+ if args.count != 2
609
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
610
+ end
611
+ connect(options)
612
+
613
+ begin
614
+ router = find_router(args[0])
615
+ return if !router
616
+
617
+ rule = router['firewall'] && router['firewall']['rules'] ? router['firewall']['rules'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
618
+
619
+ if !rule
620
+ print_red_alert "Firewall rule #{args[1]} not found for router #{router['name']}"
621
+ exit 1
622
+ end
623
+
624
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the firewall rule '#{rule['name']}' from router '#{router['name']}'?", options)
625
+ return 9, "aborted command"
626
+ end
627
+ @network_routers_interface.setopts(options)
628
+ if options[:dry_run]
629
+ print_dry_run @network_routers_interface.dry.destroy_firewall_rule(router['id'], rule['id'])
630
+ return
631
+ end
632
+ json_response = @network_routers_interface.destroy_firewall_rule(router['id'], rule['id'])
633
+ if options[:json]
634
+ print JSON.pretty_generate(json_response)
635
+ print "\n"
636
+ elsif !options[:quiet]
637
+ print_green_success "\nFirewall rule #{rule['name']} for router #{router['name']} is being removed...\n"
638
+ _firewall(router['id'], options.merge({:rules_only => true}))
639
+ end
640
+ rescue RestClient::Exception => e
641
+ print_rest_exception(e, options)
642
+ exit 1
643
+ end
644
+ end
645
+
646
+ def dhcp(args)
647
+ options = {}
648
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
649
+ opts.banner = subcommand_usage("[router]")
650
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
651
+ opts.footer = "Display network router DHCP details." + "\n" +
652
+ "[router] is required. This is the name or id of a network router."
653
+ end
654
+
655
+ optparse.parse!(args)
656
+ connect(options)
657
+
658
+ if args.count < 1
659
+ puts optparse
660
+ return 1
661
+ end
662
+
663
+ begin
664
+ @network_routers_interface.setopts(options)
665
+ if options[:dry_run]
666
+ if args[0].to_s =~ /\A\d{1,}\Z/
667
+ print_dry_run @network_routers_interface.dry.get(args[0].to_i)
668
+ else
669
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
670
+ end
671
+ return
672
+ end
673
+ router = find_router(args[0])
674
+ if router.nil?
675
+ return 1
676
+ end
677
+
678
+ json_response = {'networkRouter' => router}
679
+
680
+ if options[:json]
681
+ puts as_json(json_response, options, "networkRouter")
682
+ return 0
683
+ elsif options[:yaml]
684
+ puts as_yaml(json_response, options, "networkRouter")
685
+ return 0
686
+ elsif options[:csv]
687
+ puts records_as_csv([json_response['networkRouter']], options)
688
+ return 0
689
+ end
690
+
691
+ print_h1 "Network Router DHCP Details for: #{router['name']}"
692
+ print cyan
693
+
694
+ if router['type']['hasDhcp']
695
+ print_dhcp(router, true)
696
+ else
697
+ print_red_alert "DHCP not supported for #{router['type']['name']}"
698
+ end
699
+ println reset
700
+ rescue RestClient::Exception => e
701
+ print_rest_exception(e, options)
702
+ return 1
703
+ end
704
+ end
705
+
706
+ def routes(args)
707
+ options = {}
708
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
709
+ opts.banner = subcommand_usage("[router]")
710
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
711
+ opts.footer = "List network router routes." + "\n" +
712
+ "[router] is required. This is the name or id of a network router."
713
+ end
714
+
715
+ optparse.parse!(args)
716
+ connect(options)
717
+
718
+ if args.count < 1
719
+ puts optparse
720
+ return 1
721
+ end
722
+ _routes(args[0], options)
723
+ end
724
+
725
+ def _routes(router_id, options)
726
+ begin
727
+ @network_routers_interface.setopts(options)
728
+ if options[:dry_run]
729
+ if args[0].to_s =~ /\A\d{1,}\Z/
730
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
731
+ else
732
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
733
+ end
734
+ return
735
+ end
736
+ router = find_router(router_id)
737
+ if router.nil?
738
+ return 1
739
+ end
740
+
741
+ json_response = {'networkRouter' => router}
742
+
743
+ if options[:json]
744
+ puts as_json(json_response, options, "networkRouter")
745
+ return 0
746
+ elsif options[:yaml]
747
+ puts as_yaml(json_response, options, "networkRouter")
748
+ return 0
749
+ elsif options[:csv]
750
+ puts records_as_csv([json_response['networkRouter']], options)
751
+ return 0
752
+ end
753
+
754
+ print_h1 "Network Router Routes for: #{router['name']}"
755
+ print cyan
756
+
757
+ if router['type']['hasRouting']
758
+ print_routes(router)
759
+ else
760
+ print_red_alert "Routes not supported for #{router['type']['name']}"
761
+ end
762
+ print reset
763
+ rescue RestClient::Exception => e
764
+ print_rest_exception(e, options)
765
+ return 1
766
+ end
767
+ end
768
+
769
+ def add_route(args)
770
+ options = {:options=>{}}
771
+ params = {}
772
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
773
+ opts.banner = subcommand_usage("[router] [name]")
774
+ opts.on('-n', '--name VALUE', String, "Name for this route") do |val|
775
+ params['name'] = val
776
+ end
777
+ opts.on('-D', '--description VALUE', String, "Description") do |val|
778
+ params['description'] = val
779
+ end
780
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the route. Default is on") do |val|
781
+ options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
782
+ end
783
+ opts.on('--default [on|off]', String, "Can be used to enable / disable as default route. Default is off") do |val|
784
+ options[:defaultRoute] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
785
+ end
786
+ opts.on('--source VALUE', String, "Network for this route") do |val|
787
+ params['source'] = val
788
+ end
789
+ opts.on('--destination VALUE', String, "Next hop for this route") do |val|
790
+ params['destination'] = val
791
+ end
792
+ opts.on('--mtu VALUE', String, "MTU for this route") do |val|
793
+ params['networkMtu'] = val
794
+ end
795
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
796
+ opts.footer = "Create a network router route."
797
+ end
798
+ optparse.parse!(args)
799
+ connect(options)
800
+ if args.count < 1 || args.count > 2
801
+ print_error Morpheus::Terminal.angry_prompt
802
+ puts_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.inspect}\n#{optparse}"
803
+ return 1
804
+ end
805
+ if args.count > 1
806
+ params['name'] = args[1]
807
+ end
808
+ begin
809
+ router = find_router(args[0])
810
+
811
+ if router.nil?
812
+ return 1
813
+ end
814
+
815
+ if !router['type']['hasRouting']
816
+ print_red_alert "Routes not supported for #{router['type']['name']}"
817
+ return 1
818
+ end
819
+
820
+ if options[:payload]
821
+ payload = options[:payload]
822
+ else
823
+ params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], options[:options], @api_client, params)['name']
824
+ params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => true}], options[:options], @api_client, params)['description']
825
+
826
+ # prompt for enabled if not set
827
+ params['enabled'] = options[:enabled].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'description' => 'Enabling Route.', 'defaultValue' => true, 'required' => false}], options, @api_client, {})['enabled'] == 'on' : options[:enabled]
828
+
829
+ # default ruote
830
+ params['defaultRoute'] = options[:defaultRoute].nil? ? Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultRoute', 'fieldLabel' => 'Default Route', 'type' => 'checkbox', 'description' => 'Default Route.', 'defaultValue' => false, 'required' => false}], options, @api_client, {})['defaultRoute'] == 'on' : options[:defaultRoute]
831
+
832
+ params['source'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'type' => 'text', 'fieldLabel' => 'Network', 'required' => true}], options[:options], @api_client, params)['source']
833
+ params['destination'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'type' => 'text', 'fieldLabel' => 'Next Hop', 'required' => true}], options[:options], @api_client, params)['destination']
834
+ params['networkMtu'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkMtu', 'type' => 'text', 'fieldLabel' => 'MTU', 'required' => true}], options[:options], @api_client, params)['networkMtu']
835
+
836
+ payload = {'route' => params}
837
+ end
838
+
839
+ @network_routers_interface.setopts(options)
840
+ if options[:dry_run]
841
+ print_dry_run @network_routers_interface.dry.create_route(router['id'], payload)
842
+ return
843
+ end
844
+
845
+ json_response = @network_routers_interface.create_route(router['id'], payload)
846
+
847
+ if options[:json]
848
+ print JSON.pretty_generate(json_response), "\n"
849
+ return
850
+ end
851
+ print_green_success "\nAdded Network Router Route #{payload['route']['name']}"
852
+ _routes(router['id'], options)
853
+ rescue RestClient::Exception => e
854
+ print_rest_exception(e, options)
855
+ exit 1
856
+ end
857
+ end
858
+
859
+ def remove_route(args)
860
+ options = {}
861
+ query_params = {}
862
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
863
+ opts.banner = subcommand_usage("[router] [rule]")
864
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
865
+ opts.footer = "Delete a network router route.\n" +
866
+ "[router] is required. This is the name or id of an existing network router."
867
+ "[route] is required. This is the name or id of an existing network router route."
868
+ end
869
+ optparse.parse!(args)
870
+ if args.count != 2
871
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
872
+ end
873
+ connect(options)
874
+
875
+ begin
876
+ router = find_router(args[0])
877
+ return if !router
878
+
879
+ route = router['routes'] ? router['routes'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
880
+
881
+ if !route
882
+ print_red_alert "Route #{args[1]} not found for router #{router['name']}"
883
+ exit 1
884
+ end
885
+
886
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the route '#{route['name']}' from router '#{router['name']}'?", options)
887
+ return 9, "aborted command"
888
+ end
889
+ @network_routers_interface.setopts(options)
890
+ if options[:dry_run]
891
+ print_dry_run @network_routers_interface.dry.destroy_route(router['id'], route['id'])
892
+ return
893
+ end
894
+ json_response = @network_routers_interface.destroy_route(router['id'], route['id'])
895
+ if options[:json]
896
+ print JSON.pretty_generate(json_response)
897
+ print "\n"
898
+ elsif !options[:quiet]
899
+ print_green_success "\nRoute #{route['name']} for router #{router['name']} is being removed..."
900
+ _routes(router['id'], options)
901
+ end
902
+ rescue RestClient::Exception => e
903
+ print_rest_exception(e, options)
904
+ exit 1
905
+ end
906
+ end
907
+
908
+ def types(args)
909
+ options = {}
910
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
911
+ opts.banner = subcommand_usage()
912
+ build_common_options(opts, options, [:json, :dry_run, :remote])
913
+ opts.footer = "List network router types."
914
+ end
915
+ optparse.parse!(args)
916
+ connect(options)
917
+ begin
918
+ params = {}
919
+ params.merge!(parse_list_options(options))
920
+
921
+ @network_routers_interface.setopts(options)
922
+ if options[:dry_run]
923
+ print_dry_run @network_routers_interface.dry.types(params)
924
+ return
925
+ end
926
+
927
+ json_response = @network_routers_interface.types(params)
928
+
929
+ if options[:json]
930
+ print JSON.pretty_generate(json_response)
931
+ print "\n"
932
+ return
933
+ end
934
+
935
+ title = "Morpheus Network Router Types"
936
+ subtitles = []
937
+ subtitles += parse_list_subtitles(options)
938
+ print_h1 title, subtitles
939
+
940
+ router_types = json_response['networkRouterTypes']
941
+
942
+ if router_types.empty?
943
+ println yellow,"No network router types found.",reset
944
+ else
945
+ print as_pretty_table(router_types, {'ID' => 'id', 'NAME' => 'name'}, options)
946
+ end
947
+ println reset
948
+ return 0
949
+ rescue RestClient::Exception => e
950
+ print_rest_exception(e, options)
951
+ exit 1
952
+ end
953
+ end
954
+
955
+ def type(args)
956
+ options = {}
957
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
958
+ opts.banner = subcommand_usage("[type]")
959
+ opts.on('-t', '--type VALUE', String, "Name or ID of router type") do |val|
960
+ options[:options]['routerType'] = val
961
+ end
962
+ build_common_options(opts, options, [:list, :json, :dry_run, :remote])
963
+ opts.footer = "Display network router type details."
964
+ end
965
+ optparse.parse!(args)
966
+
967
+ if args.count > 1
968
+ print_error Morpheus::Terminal.angry_prompt
969
+ puts_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
970
+ return 1
971
+ end
972
+
973
+ if args.count > 0
974
+ options[:options]['routerType'] = args[0]
975
+ end
976
+
977
+ begin
978
+ connect(options)
979
+ @network_routers_interface.setopts(options)
980
+ if options[:dry_run]
981
+ print_dry_run @network_routers_interface.dry.types(params)
982
+ return
983
+ end
984
+
985
+ router_type = prompt_router_type(options)
986
+
987
+ if options[:json]
988
+ print JSON.pretty_generate({'networkRouterType' => router_type})
989
+ print "\n"
990
+ return
991
+ end
992
+
993
+ print_h1 "Network Router Type Details for: #{router_type['name']}"
994
+ print cyan
995
+
996
+ description_cols = {
997
+ "ID" => lambda {|it| it['id'] },
998
+ "Name" => lambda {|it| it['name'] },
999
+ "Code" => lambda {|it| it['code'] },
1000
+ "Enabled" => lambda {|it| format_boolean(it['enabled'])},
1001
+ "Creatable" => lambda {|it| format_boolean(it['creatable'])},
1002
+ "Selectable" => lambda {|it| format_boolean(it['selectable'])},
1003
+ "Firewall" => lambda {|it| format_boolean(it['hasFirewall'])},
1004
+ "DHCP" => lambda {|it| format_boolean(it['hasDhcp'])},
1005
+ "Routing" => lambda {|it| format_boolean(it['hasRouting'])},
1006
+ "Network Server" => lambda {|it| format_boolean(it['hasNetworkServer'])}
1007
+ }
1008
+ print_description_list(description_cols, router_type)
1009
+
1010
+ if router_type['optionTypes'].count > 0
1011
+ println cyan
1012
+ print Morpheus::Cli::OptionTypes.display_option_types_help(
1013
+ router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName'])},
1014
+ {:include_context => true, :context_map => {'networkRouter' => ''}, :color => cyan, :title => "Available Router Options"}
1015
+ )
1016
+ end
1017
+ print reset
1018
+ return 0
1019
+ rescue RestClient::Exception => e
1020
+ print_rest_exception(e, options)
1021
+ exit 1
1022
+ end
1023
+ end
1024
+
1025
+ def update_permissions(args)
1026
+ options = {}
1027
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1028
+ opts.banner = subcommand_usage( "[router]")
1029
+ add_perms_options(opts, options, ['plans', 'groups'])
1030
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1031
+ opts.footer = "Update a network router permissions.\n" +
1032
+ "[router] is required. This is the name or id of an existing network router."
1033
+ end
1034
+
1035
+ optparse.parse!(args)
1036
+ if args.count != 1
1037
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
1038
+ end
1039
+ connect(options)
1040
+
1041
+ begin
1042
+ if !is_master_account
1043
+ print_red_alert "Permissions only available for master account"
1044
+ return 1
1045
+ end
1046
+
1047
+ router = find_router(args[0])
1048
+ return 1 if router.nil?
1049
+
1050
+ if options[:payload]
1051
+ payload = options[:payload]
1052
+ # support -O OPTION switch on top of --payload
1053
+ if options[:options]
1054
+ payload['permissions'] ||= {}
1055
+ payload['permissions'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
1056
+ end
1057
+ else
1058
+ perms = {}
1059
+ if !options[:visibility].nil?
1060
+ perms['visibility'] = options[:visibility]
1061
+ end
1062
+ if !options[:tenants].nil?
1063
+ perms['tenantPermissions'] = {'accounts' => options[:tenants].collect {|id| id.to_i}}
1064
+ end
1065
+ payload = {'permissions' => perms}
1066
+ end
1067
+
1068
+ @network_routers_interface.setopts(options)
1069
+ if options[:dry_run]
1070
+ print_dry_run @network_routers_interface.dry.update_permissions(router['id'], payload)
1071
+ return
1072
+ end
1073
+ json_response = @network_routers_interface.update_permissions(router['id'], payload)
1074
+ if options[:json]
1075
+ print JSON.pretty_generate(json_response)
1076
+ print "\n"
1077
+ elsif json_response['success']
1078
+ print_green_success "\nUpdated Network Router Permissions\n"
1079
+ else
1080
+ print_rest_errors(json_response, options)
1081
+ end
1082
+ end
1083
+ end
1084
+
1085
+ private
1086
+
1087
+ def print_firewall(router, details=false, rules_only=false)
1088
+ if router['type']['hasFirewall']
1089
+ if router['firewall']
1090
+ if details
1091
+ description_cols = {
1092
+ "Network Router" => lambda {|it| it['name'] },
1093
+ "Enabled" => lambda {|it| format_boolean(it['firewall']['enabled'])},
1094
+ "Version" => lambda {|it| it['firewall']['version']},
1095
+ "Default Policy" => lambda {|it| (router['firewall']['defaultPolicy'] || {})['action']}
1096
+ }
1097
+ (router['firewall']['global'] || {}).each do |k,v|
1098
+ description_cols[k.gsub(/[A-Z]/, ' \0').downcase] = lambda {|it| it['firewall']['global'][k]}
1099
+ end
1100
+
1101
+ if !rules_only
1102
+ print_description_list(description_cols, router)
1103
+ print_h2 "Firewall Rules"
1104
+ end
1105
+
1106
+ if (router['firewall']['rules'] || []).count > 0
1107
+ rows = router['firewall']['rules'].collect do |it|
1108
+ {
1109
+ id: it['id'],
1110
+ name: it['name'],
1111
+ type: it['ruleType'],
1112
+ policy: it['policy'],
1113
+ direction: it['direction'] || 'any',
1114
+ source: it['source'] || 'any',
1115
+ destination: it['destination'] || 'any',
1116
+ application: it['applications'].count > 0 ? it['applications'][0]['name'] : "#{(it['protocol'] || 'any')} #{it['portRange'] || ''}"
1117
+ }
1118
+ end
1119
+ puts as_pretty_table(rows, [:id, :name, :type, :policy, :direction, :source, :destination, :application])
1120
+ else
1121
+ println "No firewall rules"
1122
+ end
1123
+ else
1124
+ print "Enabled: #{format_boolean(router['firewall']['enabled'])}".center(20)
1125
+ print "Version: #{router['firewall']['version']}".center(20)
1126
+ print "Default Policy: #{(router['firewall']['defaultPolicy'] || {})['action']}".center(20)
1127
+ println
1128
+ end
1129
+ else
1130
+ println "Enabled: #{format_boolean(false)}".center(20)
1131
+ end
1132
+ end
1133
+ end
1134
+
1135
+ def print_dhcp(router, details=false)
1136
+ if router['type']['hasDhcp']
1137
+ if router['dhcp']
1138
+ if details
1139
+ description_cols = {
1140
+ "Network Router" => lambda {|it| it['name'] },
1141
+ "Enabled" => lambda {|it| format_boolean(it['dhcp']['enabled'])},
1142
+ "Version" => lambda {|it| it['dhcp']['version']},
1143
+ "Feature" => lambda {|it| it['dhcp']['featureType']},
1144
+ "Logs Enabled" => lambda {|it| format_boolean((it['dhcp']['logging'] || {})['enable'])},
1145
+ "Log Level" => lambda {|it| (it['dhcp']['logging'] || {})['logLevel']}
1146
+ }
1147
+
1148
+ print_description_list(description_cols, router)
1149
+
1150
+ print_h2 "IP Pools"
1151
+ print cyan
1152
+
1153
+ if (router['dhcp']['ipPools'] || []).count > 0
1154
+ rows = router['dhcp']['ipPools'].collect do |it|
1155
+ {
1156
+ ip_range: it['ipRange'],
1157
+ gateway: it['defaultGateway'],
1158
+ subnet: it['subnetMask'],
1159
+ dns: it['primaryNameServer'],
1160
+ domain: it['domainName']
1161
+ }
1162
+ end
1163
+ puts as_pretty_table(rows, [:ip_range, :gateway, :subnet, :dns, :domain])
1164
+ else
1165
+ println "No IP pools"
1166
+ end
1167
+ else
1168
+ print "Enabled: #{format_boolean(router['dhcp']['enabled'])}".center(20)
1169
+ print "Version: #{router['dhcp']['version']}".center(20)
1170
+ print "Feature: #{router['dhcp']['version']}".center(20)
1171
+ print "Logs Enabled: #{(format_boolean((router['dhcp']['logging'] || {})['enable']))}".center(20)
1172
+ print "Log Level: #{(router['dhcp']['logging'] || {})['logLevel']}".center(20)
1173
+ println
1174
+ end
1175
+ else
1176
+ print "Enabled: #{format_boolean(false)}".center(20)
1177
+ print "Logs Enabled: #{format_boolean(false)}".center(20)
1178
+ println
1179
+ end
1180
+ end
1181
+ end
1182
+
1183
+ def print_routes(router)
1184
+ if router['type']['hasRouting']
1185
+ if router['routes'].count > 0
1186
+ rows = router['routes'].collect do |it|
1187
+ {
1188
+ id: it['id'],
1189
+ name: it['name'],
1190
+ network: it['source'],
1191
+ next_hop: it['destination'],
1192
+ interface: it['externalInterface'],
1193
+ default_route: format_boolean(it['defaultRoute']),
1194
+ mtu: it['networkMtu']
1195
+ }
1196
+ end
1197
+ puts as_pretty_table(rows, [:id, :name, :network, :next_hop, :interface, :default_route, :mtu])
1198
+ else
1199
+ println "No routes\n"
1200
+ end
1201
+ end
1202
+ end
1203
+
1204
+ def format_router_status(router, return_color = cyan)
1205
+ status = router['status']
1206
+ color = white
1207
+ color = green if status == 'ok'
1208
+ color = yellow if status == 'warning'
1209
+ color = red if status == 'error'
1210
+ "#{color}#{status.upcase}#{return_color}"
1211
+ end
1212
+
1213
+ def router_integration_label(router)
1214
+ integration = router['networkServer']['integration'] || {}
1215
+ integration['integrationType'] ? integration['integrationType']['name'] : router['zone']['name']
1216
+ end
1217
+
1218
+ def find_router(val)
1219
+ if val.to_s =~ /\A\d{1,}\Z/
1220
+ return find_router_by_id(val)
1221
+ else
1222
+ return find_router_by_name(val)
1223
+ end
1224
+ end
1225
+
1226
+ def find_router_by_id(id)
1227
+ begin
1228
+ json_response = @network_routers_interface.get(id.to_i)
1229
+ return json_response['networkRouter']
1230
+ rescue RestClient::Exception => e
1231
+ if e.response && e.response.code == 404
1232
+ print_red_alert "Network Router not found by id #{id}"
1233
+ return nil
1234
+ else
1235
+ raise e
1236
+ end
1237
+ end
1238
+ end
1239
+
1240
+ def find_router_by_name(name)
1241
+ json_response = @network_routers_interface.list({phrase: name.to_s})
1242
+ routers = json_response['networkRouters']
1243
+ if routers.empty?
1244
+ print_red_alert "Network Router not found by name #{name}"
1245
+ return nil
1246
+ elsif routers.size > 1
1247
+ print_red_alert "#{routers.size} network routers found by name #{name}"
1248
+ rows = routers.collect do |it|
1249
+ {id: it['id'], name: it['name']}
1250
+ end
1251
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1252
+ return nil
1253
+ else
1254
+ return routers[0]
1255
+ end
1256
+ end
1257
+
1258
+ def find_router_type(val)
1259
+ types = @network_routers_interface.types()['networkRouterTypes']
1260
+ (val.to_s =~ /\A\d{1,}\Z/) ? types.find {|it| it['id'].to_i == val.to_i} : types.find {|it| it['name'] == val}
1261
+ end
1262
+
1263
+ def prompt_router_type(options)
1264
+ if options[:options]['routerType']
1265
+ router_type = find_router_type(options[:options]['routerType'])
1266
+ if router_type.nil?
1267
+ print_red_alert "Network router type #{options[:options]['routerType']} not found"
1268
+ exit 1
1269
+ end
1270
+ else
1271
+ router_types = @network_routers_interface.types()['networkRouterTypes']
1272
+ router_type_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'routerType', 'type' => 'select', 'fieldLabel' => 'Network Router Type', 'required' => true, 'selectOptions' => router_types.collect {|it| {'name' => it['name'], 'value' => it['id']}}}], options[:options], @api_client,{}, nil, true)['routerType']
1273
+ router_type = router_types.find {|type| type['id'] == router_type_id}
1274
+ end
1275
+ router_type
1276
+ end
1277
+
1278
+ def available_groups()
1279
+ @network_routers_interface.groups
1280
+ end
1281
+ end