morpheus-cli 4.1.14 → 4.2

Sign up to get free protection for your applications and to get access to all the features.
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