morpheus-cli 5.3.2 → 5.3.3

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/accounts_interface.rb +4 -30
  4. data/lib/morpheus/api/api_client.rb +12 -0
  5. data/lib/morpheus/api/instances_interface.rb +18 -5
  6. data/lib/morpheus/api/load_balancer_pools_interface.rb +9 -0
  7. data/lib/morpheus/api/load_balancer_types_interface.rb +9 -0
  8. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +9 -0
  9. data/lib/morpheus/api/load_balancers_interface.rb +4 -53
  10. data/lib/morpheus/api/network_routers_interface.rb +56 -0
  11. data/lib/morpheus/api/secondary_read_interface.rb +25 -0
  12. data/lib/morpheus/api/secondary_rest_interface.rb +42 -0
  13. data/lib/morpheus/api/virtual_images_interface.rb +23 -2
  14. data/lib/morpheus/cli/apps.rb +3 -2
  15. data/lib/morpheus/cli/cli_command.rb +21 -14
  16. data/lib/morpheus/cli/cli_registry.rb +55 -2
  17. data/lib/morpheus/cli/cloud_resource_pools_command.rb +169 -133
  18. data/lib/morpheus/cli/clusters.rb +51 -33
  19. data/lib/morpheus/cli/instances.rb +292 -174
  20. data/lib/morpheus/cli/invoices_command.rb +79 -99
  21. data/lib/morpheus/cli/library_cluster_layouts_command.rb +20 -0
  22. data/lib/morpheus/cli/load_balancer_types.rb +37 -0
  23. data/lib/morpheus/cli/load_balancers.rb +149 -314
  24. data/lib/morpheus/cli/log_settings_command.rb +7 -3
  25. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +156 -0
  26. data/lib/morpheus/cli/mixins/print_helper.rb +11 -0
  27. data/lib/morpheus/cli/mixins/provisioning_helper.rb +123 -101
  28. data/lib/morpheus/cli/mixins/rest_command.rb +657 -0
  29. data/lib/morpheus/cli/monitoring_checks_command.rb +2 -0
  30. data/lib/morpheus/cli/network_routers_command.rb +1183 -185
  31. data/lib/morpheus/cli/networks_command.rb +194 -101
  32. data/lib/morpheus/cli/option_parser.rb +25 -17
  33. data/lib/morpheus/cli/option_types.rb +42 -45
  34. data/lib/morpheus/cli/tenants_command.rb +18 -20
  35. data/lib/morpheus/cli/vdi_pools_command.rb +4 -1
  36. data/lib/morpheus/cli/version.rb +1 -1
  37. data/lib/morpheus/cli/virtual_images.rb +249 -29
  38. data/lib/morpheus/cli.rb +1 -0
  39. data/lib/morpheus/ext/string.rb +41 -0
  40. data/lib/morpheus/formatters.rb +4 -0
  41. data/morpheus-cli.gemspec +1 -1
  42. metadata +13 -4
@@ -158,11 +158,13 @@ class Morpheus::Cli::MonitoringChecksCommand
158
158
  end
159
159
  },
160
160
  "Type" => lambda {|it| format_monitoring_check_type(it) },
161
+ "API Key" => lambda {|it| it['apiKey'] },
161
162
  "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : "System" },
162
163
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
163
164
  "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
164
165
  # "Last Error" => lambda {|it| format_local_dt(it['lastErrorDate']) },
165
166
  }
167
+ description_cols.delete("API Key") if !['pushCheck'].include?(check['checkType']['code']) || check['apiKey'].nil?
166
168
  print_description_list(description_cols, check)
167
169
 
168
170
  # Last Error
@@ -11,10 +11,12 @@ class Morpheus::Cli::NetworkRoutersCommand
11
11
  include Morpheus::Cli::WhoamiHelper
12
12
 
13
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
14
+ register_subcommands :list, :get, :firewall, :dhcp, :types, :type, :add, :update, :remove
15
+ register_subcommands :add_firewall_rule_group, :update_firewall_rule_group, :remove_firewall_rule_group, :firewall_rule_groups, :firewall_rule_group
16
+ register_subcommands :add_firewall_rule, :update_firewall_rule, :remove_firewall_rule, :firewall_rules, :firewall_rule
17
+ register_subcommands :add_route, :remove_route, :routes
17
18
  register_subcommands :update_permissions
19
+ register_subcommands :add_nat, :update_nat, :remove_nat, :nats, :nat
18
20
 
19
21
  def initialize()
20
22
  end
@@ -107,7 +109,7 @@ class Morpheus::Cli::NetworkRoutersCommand
107
109
  options = {}
108
110
  optparse = Morpheus::Cli::OptionParser.new do |opts|
109
111
  opts.banner = subcommand_usage("[router]")
110
- opts.on('--details', "Display details: firewall, DHCP, and routing." ) do
112
+ opts.on('--details', "Display details: firewall, DHCP, routing, and NATs." ) do
111
113
  options[:details] = true
112
114
  end
113
115
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
@@ -192,7 +194,7 @@ class Morpheus::Cli::NetworkRoutersCommand
192
194
  if router['type']['hasFirewall']
193
195
  print_h2 "Firewall"
194
196
  print cyan
195
- print_firewall(router, options[:details])
197
+ print_firewall(router, options)
196
198
  end
197
199
  if router['type']['hasDhcp']
198
200
  print_h2 "DHCP"
@@ -204,6 +206,11 @@ class Morpheus::Cli::NetworkRoutersCommand
204
206
  print cyan
205
207
  print_routes(router)
206
208
  end
209
+ if router['type']['hasNat'] && options[:details]
210
+ print_h2 "NATs"
211
+ print cyan
212
+ print_nats(router)
213
+ end
207
214
  if router['permissions'] && options[:details]
208
215
  print_h2 "Tenant Permissions"
209
216
  print cyan
@@ -360,9 +367,15 @@ class Morpheus::Cli::NetworkRoutersCommand
360
367
  params = {}
361
368
  optparse = Morpheus::Cli::OptionParser.new do|opts|
362
369
  opts.banner = subcommand_usage("[router]")
363
- opts.on('-D', '--description VALUE', String, "Description") do |val|
370
+ opts.on('-n', '--name VALUE', String, "Name for this network") do |val|
371
+ params['name'] = val
372
+ end
373
+ opts.on('-D', '--description VALUE', String, "Description for this network") do |val|
364
374
  params['description'] = val
365
375
  end
376
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the network router. Default is on") do |val|
377
+ options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
378
+ end
366
379
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
367
380
  opts.footer = "Update a network router."
368
381
  end
@@ -388,7 +401,7 @@ class Morpheus::Cli::NetworkRoutersCommand
388
401
  end
389
402
 
390
403
  if options[:options]
391
- params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) || ['name', 'routerType'].include?(k)})
404
+ params.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) || ['name', 'routerType', 'enabled', 'description'].include?(k)})
392
405
  end
393
406
  payload = {'networkRouter' => params}
394
407
  end
@@ -468,6 +481,9 @@ class Morpheus::Cli::NetworkRoutersCommand
468
481
  options = {}
469
482
  optparse = Morpheus::Cli::OptionParser.new do |opts|
470
483
  opts.banner = subcommand_usage("[router]")
484
+ opts.on('--details', "Display details." ) do
485
+ options[:details] = true
486
+ end
471
487
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
472
488
  opts.footer = "Display network router firewall details." + "\n" +
473
489
  "[router] is required. This is the name or id of a network router."
@@ -480,21 +496,18 @@ class Morpheus::Cli::NetworkRoutersCommand
480
496
  puts optparse
481
497
  return 1
482
498
  end
483
- _firewall(args[0], options)
484
- end
485
499
 
486
- def _firewall(router_id, options)
487
500
  begin
488
501
  @network_routers_interface.setopts(options)
489
502
  if options[:dry_run]
490
503
  if args[0].to_s =~ /\A\d{1,}\Z/
491
- print_dry_run @network_routers_interface.dry.get(router_id.to_i)
504
+ print_dry_run @network_routers_interface.dry.get(args[0].to_i)
492
505
  else
493
- print_dry_run @network_routers_interface.dry.list({name:router_id})
506
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
494
507
  end
495
508
  return
496
509
  end
497
- router = find_router(router_id)
510
+ router = find_router(args[0])
498
511
  if router.nil?
499
512
  return 1
500
513
  end
@@ -512,34 +525,930 @@ class Morpheus::Cli::NetworkRoutersCommand
512
525
  return 0
513
526
  end
514
527
 
515
- if !options[:rules_only]
516
- print_h1 "Network Router Firewall Details for: #{router['name']}"
517
- end
518
-
528
+ print_h1 "Network Router Firewall Details For: #{router['name']}"
519
529
  print cyan
520
530
 
521
531
  if router['type']['hasFirewall']
522
- print_firewall(router, true, options[:rules_only])
532
+ print_firewall(router, options)
523
533
  else
524
534
  print_red_alert "Firewall not supported for #{router['type']['name']}"
525
535
  end
526
- println reset
527
- rescue RestClient::Exception => e
528
- print_rest_exception(e, options)
529
- return 1
530
- end
531
- end
532
-
533
- def add_firewall_rule(args)
534
- options = {:options=>{}}
535
- params = {}
536
- optparse = Morpheus::Cli::OptionParser.new do|opts|
537
- opts.banner = subcommand_usage("[router] [name]")
538
- opts.on('-n', '--name VALUE', String, "Name for this firewall rule") do |val|
539
- params['name'] = val
536
+ println reset
537
+ rescue RestClient::Exception => e
538
+ print_rest_exception(e, options)
539
+ return 1
540
+ end
541
+ end
542
+
543
+ def firewall_rule_groups(args)
544
+ options = {}
545
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
546
+ opts.banner = subcommand_usage("[router]")
547
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
548
+ opts.footer = "Display network router firewall rule groups.\n" +
549
+ "[router] is required. This is the name or id of a network router."
550
+ end
551
+
552
+ optparse.parse!(args)
553
+ connect(options)
554
+
555
+ if args.count < 1
556
+ puts optparse
557
+ return 1
558
+ end
559
+
560
+ begin
561
+ @network_routers_interface.setopts(options)
562
+ if options[:dry_run]
563
+ if router_id.to_s =~ /\A\d{1,}\Z/
564
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
565
+ else
566
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
567
+ end
568
+ return
569
+ end
570
+
571
+ router = find_router(args[0])
572
+ if router.nil?
573
+ return 1
574
+ end
575
+ _firewall_rule_groups(router, options)
576
+ rescue RestClient::Exception => e
577
+ print_rest_exception(e, options)
578
+ return 1
579
+ end
580
+ end
581
+
582
+ def _firewall_rule_groups(router, options)
583
+ if router['type']['hasFirewallGroups']
584
+ json_response = {'ruleGroups' => router['firewall']['ruleGroups'] || []}
585
+
586
+ if options[:json]
587
+ puts as_json(json_response, options, "ruleGroups")
588
+ return 0
589
+ elsif options[:yaml]
590
+ puts as_yaml(json_response, options, "ruleGroups")
591
+ return 0
592
+ elsif options[:csv]
593
+ puts records_as_csv(json_response['ruleGroups'], options)
594
+ return 0
595
+ end
596
+
597
+ if (router['firewall']['ruleGroups'] || []).count > 0
598
+ print_h1 "Firewall Rule Groups For: #{router['name']}"
599
+ rows = router['firewall']['ruleGroups'].collect do |rule_group|
600
+ {
601
+ id: rule_group['id'],
602
+ name: rule_group['name'],
603
+ description: rule_group['description'],
604
+ priority: rule_group['priority'],
605
+ category: rule_group['groupLayer']
606
+ }
607
+ end
608
+ rows = rows.reject {|it| it[:id].to_s != options[:rule_group_id].to_s} if options[:rule_group_id]
609
+ puts as_pretty_table(rows, [:id, :name, :description, :priority, :category])
610
+ else
611
+ print_h1 "No Firewall Rule Groups"
612
+ end
613
+ else
614
+ print_red_alert "Firewall rule groups not supported for #{router['type']['name']}"
615
+ end
616
+ println reset
617
+ end
618
+
619
+ def firewall_rule_group(args)
620
+ options = {}
621
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
622
+ opts.banner = subcommand_usage("[router]")
623
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
624
+ opts.footer = "Display network router firewall rule group details." + "\n" +
625
+ "[router] is required. This is the name or id of a network router.\n" +
626
+ "[group] is required. This is the name or id of a firewall rule group.\n"
627
+ end
628
+
629
+ optparse.parse!(args)
630
+ connect(options)
631
+
632
+ if args.count < 2
633
+ puts optparse
634
+ return 1
635
+ end
636
+ _firewall_rule_group(args[0], args[1], options)
637
+ end
638
+
639
+ def _firewall_rule_group(router_id, group_id, options)
640
+ begin
641
+ @network_routers_interface.setopts(options)
642
+ if options[:dry_run]
643
+ if args[0].to_s =~ /\A\d{1,}\Z/
644
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
645
+ else
646
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
647
+ end
648
+ return
649
+ end
650
+ router = find_router(router_id)
651
+ if router.nil?
652
+ return 1
653
+ end
654
+
655
+ if router['type']['hasFirewallGroups']
656
+ group = (router['firewall']['ruleGroups'] || []).find {|it| it['id'].to_s == group_id.to_s || it['name'] == group_id.to_s}
657
+
658
+ if group
659
+ json_response = {'ruleGroup' => group}
660
+
661
+ if options[:json]
662
+ puts as_json(json_response, options, "ruleGroup")
663
+ return 0
664
+ elsif options[:yaml]
665
+ puts as_yaml(json_response, options, "ruleGroup")
666
+ return 0
667
+ elsif options[:csv]
668
+ puts records_as_csv([json_response['ruleGroup']], options)
669
+ return 0
670
+ end
671
+
672
+ print_h1 "Firewall Rule Group Details"
673
+ print cyan
674
+ description_cols = {
675
+ "ID" => lambda {|it| it['id'] },
676
+ "Name" => lambda {|it| it['name'] },
677
+ "Description" => lambda {|it| it['description']},
678
+ "Priority" => lambda {|it| it['priority']},
679
+ "Category" => lambda {|it| it['groupLayer']}
680
+ }
681
+ print_description_list(description_cols, group)
682
+ else
683
+ print_red_alert "Firewall rule group #{group_id} not found for router #{router['name']}"
684
+ end
685
+ else
686
+ print_h1 "No Firewall Rule Groups"
687
+ end
688
+ println reset
689
+ rescue RestClient::Exception => e
690
+ print_rest_exception(e, options)
691
+ return 1
692
+ end
693
+ end
694
+
695
+ def add_firewall_rule_group(args)
696
+ options = {:options=>{}}
697
+ params = {}
698
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
699
+ opts.banner = subcommand_usage("[router] [name]")
700
+ opts.on('-n', '--name VALUE', String, "Name for this firewall rule group") do |val|
701
+ params['name'] = val
702
+ end
703
+ opts.on('-D', '--description VALUE', String, "Description for this firewall rule group") do |val|
704
+ params['description'] = val
705
+ end
706
+ opts.on('--priority VALUE', Integer, "Priority for this firewall rule group (not applicable to all firewall types)") do |val|
707
+ params['priority'] = val
708
+ end
709
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
710
+ opts.footer = "Create a network router firewall rule group."
711
+ end
712
+ optparse.parse!(args)
713
+ connect(options)
714
+ if args.count < 1 || args.count > 2
715
+ print_error Morpheus::Terminal.angry_prompt
716
+ puts_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.inspect}\n#{optparse}"
717
+ return 1
718
+ end
719
+ if args.count > 1
720
+ params['name'] = args[1]
721
+ end
722
+ begin
723
+ router = find_router(args[0])
724
+
725
+ if router.nil?
726
+ return 1
727
+ end
728
+
729
+ if !router['type']['hasFirewallGroups']
730
+ print_red_alert "Firewall rule groups not supported for #{router['type']['name']}"
731
+ return 1
732
+ end
733
+
734
+ if options[:payload]
735
+ payload = options[:payload]
736
+ else
737
+ params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Group Name', 'required' => true}], options[:options], @api_client, params)['name']
738
+ params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false}], options[:options], @api_client, params)['description']
739
+
740
+ if router['type']['hasSecurityGroupPriority']
741
+ params['priority'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priority', 'type' => 'number', 'fieldLabel' => 'Priority', 'required' => false}], options[:options], @api_client, params)['priority']
742
+ end
743
+
744
+ option_types = router['type']['ruleGroupOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
745
+
746
+ # prompt options
747
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'group' => ''}}), @api_client, {}, nil, true)
748
+ payload = {'ruleGroup' => params.deep_merge(option_result)}
749
+ end
750
+
751
+ @network_routers_interface.setopts(options)
752
+ if options[:dry_run]
753
+ print_dry_run @network_routers_interface.dry.create_firewall_rule_group(router['id'], payload)
754
+ return
755
+ end
756
+
757
+ json_response = @network_routers_interface.create_firewall_rule_group(router['id'], payload)
758
+
759
+ if options[:json]
760
+ print JSON.pretty_generate(json_response), "\n"
761
+ return
762
+ end
763
+ print_green_success "\nAdded Network Router Firewall Rule Group #{payload['ruleGroup']['name']}\n"
764
+ _firewall_rule_group(router['id'], json_response['id'], options)
765
+ rescue RestClient::Exception => e
766
+ print_rest_exception(e, options)
767
+ exit 1
768
+ end
769
+ end
770
+
771
+ def update_firewall_rule_group(args)
772
+ options = {:options=>{}}
773
+ params = {}
774
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
775
+ opts.banner = subcommand_usage("[router] [name]")
776
+ opts.on('-n', '--name VALUE', String, "Name for this firewall rule group") do |val|
777
+ params['name'] = val
778
+ end
779
+ opts.on('-D', '--description VALUE', String, "Description for this firewall rule group") do |val|
780
+ params['description'] = val
781
+ end
782
+ opts.on('--priority VALUE', Integer, "Priority for this firewall rule group (not applicable to all firewall types)") do |val|
783
+ params['priority'] = val
784
+ end
785
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
786
+ opts.footer = "Update a network router firewall rule group.\n" +
787
+ "[router] is required. This is the name or id of an existing network router.\n" +
788
+ "[name] is required. This is the name or id of an existing network router firewall rule group."
789
+ end
790
+
791
+ optparse.parse!(args)
792
+ if args.count != 2
793
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
794
+ end
795
+ connect(options)
796
+
797
+ begin
798
+ router = find_router(args[0])
799
+
800
+ if router.nil?
801
+ return 1
802
+ end
803
+
804
+ if !router['type']['hasFirewallGroups']
805
+ print_red_alert "Firewall rule group not supported for #{router['type']['name']}"
806
+ return 1
807
+ end
808
+
809
+ group = router['firewall'] && router['firewall']['ruleGroups'] ? router['firewall']['ruleGroups'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
810
+
811
+ if !group
812
+ print_red_alert "Firewall rule group #{args[1]} not found for router #{router['name']}"
813
+ exit 1
814
+ end
815
+
816
+ payload = parse_payload(options) || {'ruleGroup' => params}
817
+ payload['ruleGroup'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
818
+
819
+ if payload['ruleGroup'].empty?
820
+ print_green_success "Nothing to update"
821
+ exit 1
822
+ end
823
+
824
+ @network_routers_interface.setopts(options)
825
+ if options[:dry_run]
826
+ print_dry_run @network_routers_interface.dry.update_firewall_rule_group(router['id'], group['id'], payload)
827
+ return
828
+ end
829
+
830
+ json_response = @network_routers_interface.update_firewall_rule_group(router['id'], group['id'], payload)
831
+
832
+ if options[:json]
833
+ print JSON.pretty_generate(json_response), "\n"
834
+ return
835
+ end
836
+ print_green_success "\nUpdated Network Router Firewall Rule Group #{payload['ruleGroup']['name']}\n"
837
+ _firewall_rule_group(router['id'], args[1], options)
838
+ rescue RestClient::Exception => e
839
+ print_rest_exception(e, options)
840
+ exit 1
841
+ end
842
+ end
843
+
844
+ def remove_firewall_rule_group(args)
845
+ options = {}
846
+ query_params = {}
847
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
848
+ opts.banner = subcommand_usage("[router] [group]")
849
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
850
+ opts.footer = "Delete a network router firewall rule group.\n" +
851
+ "[router] is required. This is the name or id of an existing network router."
852
+ "[group] is required. This is the name or id of an existing network router firewall rule group."
853
+ end
854
+ optparse.parse!(args)
855
+ if args.count != 2
856
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
857
+ end
858
+ connect(options)
859
+
860
+ begin
861
+ router = find_router(args[0])
862
+ return if !router
863
+
864
+ group = router['firewall'] && router['firewall']['ruleGroups'] ? router['firewall']['ruleGroups'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
865
+
866
+ if !group
867
+ print_red_alert "Firewall rule group #{args[1]} not found for router #{router['name']}"
868
+ exit 1
869
+ end
870
+
871
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the firewall rule group '#{group['name']}' from router '#{router['name']}'?", options)
872
+ return 9, "aborted command"
873
+ end
874
+ @network_routers_interface.setopts(options)
875
+ if options[:dry_run]
876
+ print_dry_run @network_routers_interface.dry.destroy_firewall_rule_group(router['id'], group['id'])
877
+ return
878
+ end
879
+ json_response = @network_routers_interface.destroy_firewall_rule_group(router['id'], group['id'])
880
+ if options[:json]
881
+ print JSON.pretty_generate(json_response)
882
+ print "\n"
883
+ elsif !options[:quiet]
884
+ print_green_success "\nFirewall rule group #{group['name']} for router #{router['name']} is being removed...\n"
885
+ _firewall_rule_groups(find_router(router['id']), options)
886
+ end
887
+ rescue RestClient::Exception => e
888
+ print_rest_exception(e, options)
889
+ exit 1
890
+ end
891
+ end
892
+
893
+ def firewall_rules(args)
894
+ options = {}
895
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
896
+ opts.banner = subcommand_usage("[router]")
897
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
898
+ opts.footer = "Display network router firewall rules.\n" +
899
+ "[router] is required. This is the name or id of a network router."
900
+ end
901
+
902
+ optparse.parse!(args)
903
+ connect(options)
904
+
905
+ if args.count < 1
906
+ puts optparse
907
+ return 1
908
+ end
909
+
910
+ begin
911
+ @network_routers_interface.setopts(options)
912
+ if options[:dry_run]
913
+ if args[0].to_s =~ /\A\d{1,}\Z/
914
+ print_dry_run @network_routers_interface.dry.get(args[0].to_i)
915
+ else
916
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
917
+ end
918
+ return
919
+ end
920
+ router = find_router(args[0])
921
+ if router.nil?
922
+ return 1
923
+ end
924
+
925
+ _firewall_rules(router, options)
926
+ rescue RestClient::Exception => e
927
+ print_rest_exception(e, options)
928
+ return 1
929
+ end
930
+ end
931
+
932
+ def _firewall_rules(router, options)
933
+ if router['type']['hasFirewall']
934
+ rules = router['type']['hasFirewallGroups'] ? (router['firewall']['ruleGroups'] || []).collect {|it| it['rules']}.flatten : router['firewall']['rules']
935
+
936
+ json_response = {'rules' => rules}
937
+
938
+ if options[:json]
939
+ puts as_json(json_response, options, "rules")
940
+ return 0
941
+ elsif options[:yaml]
942
+ puts as_yaml(json_response, options, "rules")
943
+ return 0
944
+ elsif options[:csv]
945
+ puts records_as_csv(json_response['rules'], options)
946
+ return 0
947
+ end
948
+
949
+ if router['type']['hasFirewallGroups']
950
+ rules = []
951
+ (router['firewall']['ruleGroups'] || []).each do |rule_group|
952
+ (rule_group['rules'] || []).each do |rule|
953
+ rule['groupId'] = rule_group['id']
954
+ rule['groupName'] ||= rule_group['name']
955
+ rules << rule
956
+ end
957
+ end
958
+ end
959
+
960
+ if rules.count > 0
961
+ print_h1 "Firewall Rules For: #{router['name']}"
962
+ rows = rules.collect do |it|
963
+ {
964
+ id: it['id'],
965
+ group_name: it['groupName'],
966
+ name: it['name'],
967
+ type: it['ruleType'],
968
+ policy: it['policy'],
969
+ direction: it['direction'] || 'any',
970
+ source: it['source'].kind_of?(Array) && it['source'].count > 0 ? it['source'].join(', ') : (it['source'].nil? || it['source'].empty? ? 'any' : it['source']),
971
+ destination: it['destination'].kind_of?(Array) && it['destination'].count > 0 ? it['destination'].join(', ') : (it['destination'].nil? || it['destination'].empty? ? 'any' : it['destination']),
972
+ application: it['applications'].count > 0 ? it['applications'][0]['name'] : "#{(it['protocol'] || 'any')} #{it['portRange'] || ''}"
973
+ }
974
+ end
975
+
976
+ if router['type']['hasFirewallGroups']
977
+ puts as_pretty_table(rows, [:id, :group_name, :name, :type, :policy, :direction, :source, :destination, :application])
978
+ else
979
+ puts as_pretty_table(rows, [:id, :name, :type, :policy, :direction, :source, :destination, :application])
980
+ end
981
+ else
982
+ print_h1 "No Firewall Rules"
983
+ end
984
+ else
985
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
986
+ end
987
+ println reset
988
+ end
989
+
990
+ def firewall_rule(args)
991
+ options = {}
992
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
993
+ opts.banner = subcommand_usage("[router] [rule]")
994
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
995
+ opts.footer = "Display network router firewall rule details." + "\n" +
996
+ "[router] is required. This is the name or id of a network router.\n" +
997
+ "[rule] is required. This is the name or id of a firewall rule.\n"
998
+ end
999
+
1000
+ optparse.parse!(args)
1001
+ connect(options)
1002
+
1003
+ if args.count < 2
1004
+ puts optparse
1005
+ return 1
1006
+ end
1007
+ _firewall_rule(args[0], args[1], options)
1008
+ end
1009
+
1010
+ def _firewall_rule(router_id, rule_id, options)
1011
+ begin
1012
+ @network_routers_interface.setopts(options)
1013
+ if options[:dry_run]
1014
+ if args[0].to_s =~ /\A\d{1,}\Z/
1015
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
1016
+ else
1017
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
1018
+ end
1019
+ return
1020
+ end
1021
+ router = find_router(router_id)
1022
+ if router.nil?
1023
+ return 1
1024
+ end
1025
+
1026
+ if router['type']['hasFirewall']
1027
+ rule = find_firewall_rule(router, rule_id)
1028
+
1029
+ if rule
1030
+ json_response = {'rule' => rule}
1031
+
1032
+ if options[:json]
1033
+ puts as_json(json_response, options, "rule")
1034
+ return 0
1035
+ elsif options[:yaml]
1036
+ puts as_yaml(json_response, options, "rule")
1037
+ return 0
1038
+ elsif options[:csv]
1039
+ puts records_as_csv([json_response['rule']], options)
1040
+ return 0
1041
+ end
1042
+
1043
+ print_h1 "Firewall Rule Details"
1044
+ print cyan
1045
+ description_cols = {
1046
+ "ID" => lambda {|it| it['id'] },
1047
+ "Enabled" => lambda {|it| format_boolean(it['enabled'])},
1048
+ "Priority" => lambda {|it| it['priority']},
1049
+ "Name" => lambda {|it| it['name'] },
1050
+ "Type" => lambda {|it| it['ruleType'] },
1051
+ "Policy" => lambda {|it| it['policy'] },
1052
+ "Direction" => lambda {|it| it['direction'] || 'any' },
1053
+ "Source" => lambda {|it| it['source'].kind_of?(Array) && it['source'].count > 0 ? it['source'].join(', ') : (it['source'].nil? || it['source'].empty? ? 'any' : it['source']) },
1054
+ "Destination" => lambda {|it| it['destination'].kind_of?(Array) && it['destination'].count > 0 ? it['destination'].join(', ') : (it['destination'].nil? || it['destination'].empty? ? 'any' : it['destination'])},
1055
+ "Application" => lambda {|it| it['applications'].count > 0 ? it['applications'][0]['name'] : "#{(it['protocol'] || 'any')} #{it['portRange'] || ''}"}
1056
+ }
1057
+ print_description_list(description_cols, rule)
1058
+ else
1059
+ print_red_alert "Firewall rule #{rule_id} not found for router #{router['name']}"
1060
+ end
1061
+ else
1062
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
1063
+ end
1064
+ println reset
1065
+ rescue RestClient::Exception => e
1066
+ print_rest_exception(e, options)
1067
+ return 1
1068
+ end
1069
+ end
1070
+
1071
+ def add_firewall_rule(args)
1072
+ options = {:options=>{}}
1073
+ params = {}
1074
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
1075
+ opts.banner = subcommand_usage("[router] [name]")
1076
+ opts.on('-n', '--name VALUE', String, "Name for this firewall rule") do |val|
1077
+ params['name'] = val
1078
+ end
1079
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the rule. Default is on") do |val|
1080
+ params['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
1081
+ end
1082
+ opts.on( '-g', '--group GROUP', "Firewall rule group name or ID (not applicable to all firewall types)" ) do |val|
1083
+ options[:group] = val
1084
+ end
1085
+ opts.on('--priority VALUE', Integer, "Priority for this rule (not applicable to all firewall types)") do |val|
1086
+ params['priority'] = val
1087
+ end
1088
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1089
+ opts.footer = "Create a network router firewall rule."
1090
+ end
1091
+ optparse.parse!(args)
1092
+ connect(options)
1093
+ if args.count < 1 || args.count > 2
1094
+ print_error Morpheus::Terminal.angry_prompt
1095
+ puts_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.inspect}\n#{optparse}"
1096
+ return 1
1097
+ end
1098
+ if args.count > 1
1099
+ params['name'] = args[1]
1100
+ end
1101
+ begin
1102
+ router = find_router(args[0])
1103
+
1104
+ if router.nil?
1105
+ return 1
1106
+ end
1107
+
1108
+ if !router['type']['hasFirewall']
1109
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
1110
+ return 1
1111
+ end
1112
+
1113
+ if options[:payload]
1114
+ payload = options[:payload]
1115
+ else
1116
+ params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Rule Name', 'required' => true}], options[:options], @api_client, params)['name']
1117
+
1118
+ if router['type']['hasFirewallGroups']
1119
+ if !router['firewall']['ruleGroups'].count
1120
+ print_red_alert "No firewall rule group found for #{router['type']['name']}"
1121
+ return 1
1122
+ end
1123
+
1124
+ if options[:group]
1125
+ group = router['firewall']['ruleGroups'].find {|it| it['name'] == options[:group] || it['id'] == options[:group].to_i}
1126
+ if !group
1127
+ print_red_alert "Firewall rule group #{options[:group]} not found for #{router['type']['name']}"
1128
+ return 1
1129
+ end
1130
+ group_id = group['id']
1131
+ else
1132
+ group_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Rule Group', 'required' => true, 'selectOptions' => router['firewall']['ruleGroups'].collect {|it| {'name' => it['name'], 'value' => it['id']}}}])['group']
1133
+ end
1134
+
1135
+ params['config'] = {} if params['config'].nil?
1136
+ params['config']['parentId'] = "group-#{group_id}"
1137
+ end
1138
+
1139
+ params['enabled'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'description' => 'Enable Rule.', 'defaultValue' => true, 'required' => false}], options, @api_client, {})['enabled'] == 'on'
1140
+
1141
+ if router['type']['code'].start_with?('nsx-t')
1142
+ params['priority'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priority', 'type' => 'number', 'fieldLabel' => 'Priority', 'required' => false}], options[:options], @api_client, params)['priority']
1143
+ end
1144
+
1145
+ option_types = router['type']['ruleOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
1146
+
1147
+ # prompt options
1148
+ api_params = {}
1149
+ api_params['networkServerId'] = router['networkServer']['id'] if router['networkServer']
1150
+ api_params['zoneId'] = router['zone']['id'] if router['networkServer'].nil?
1151
+ api_params['groupId'] = options[:group] if !options[:group].nil?
1152
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'rule' => ''}}), @api_client, api_params, nil, true)
1153
+ payload = {'rule' => params.deep_merge(option_result)}
1154
+ end
1155
+
1156
+ @network_routers_interface.setopts(options)
1157
+ if options[:dry_run]
1158
+ print_dry_run @network_routers_interface.dry.create_firewall_rule(router['id'], payload)
1159
+ return
1160
+ end
1161
+
1162
+ json_response = @network_routers_interface.create_firewall_rule(router['id'], payload)
1163
+
1164
+ if options[:json]
1165
+ print JSON.pretty_generate(json_response), "\n"
1166
+ return
1167
+ end
1168
+ print_green_success "\nAdded Network Router Firewall Rule #{payload['rule']['name']}\n"
1169
+ _firewall_rule(router['id'], json_response['id'], options)
1170
+ rescue RestClient::Exception => e
1171
+ print_rest_exception(e, options)
1172
+ exit 1
1173
+ end
1174
+ end
1175
+
1176
+ def update_firewall_rule(args)
1177
+ options = {:options=>{}}
1178
+ params = {}
1179
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
1180
+ opts.banner = subcommand_usage("[router] [name]")
1181
+ opts.on('-n', '--name VALUE', String, "Name for this firewall rule") do |val|
1182
+ params['name'] = val
1183
+ end
1184
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the rule. Default is on") do |val|
1185
+ params['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
1186
+ end
1187
+ opts.on('--priority VALUE', Integer, "Priority for this rule (not applicable to all firewall types)") do |val|
1188
+ params['priority'] = val
1189
+ end
1190
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1191
+ opts.footer = "Update a network router firewall rule.\n" +
1192
+ "[router] is required. This is the name or id of an existing network router.\n" +
1193
+ "[name] is required. This is the name or id of an existing network router firewall rule."
1194
+ end
1195
+
1196
+ optparse.parse!(args)
1197
+ if args.count != 2
1198
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1199
+ end
1200
+ connect(options)
1201
+
1202
+ begin
1203
+ router = find_router(args[0])
1204
+
1205
+ if router.nil?
1206
+ return 1
1207
+ end
1208
+
1209
+ if !router['type']['hasFirewall']
1210
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
1211
+ return 1
1212
+ end
1213
+
1214
+ rule = find_firewall_rule(router, args[1])
1215
+
1216
+ if !rule
1217
+ print_red_alert "Firewall rule #{args[1]} not found for router #{router['name']}"
1218
+ exit 1
1219
+ end
1220
+
1221
+ payload = parse_payload(options) || {'rule' => params}
1222
+ payload['rule'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
1223
+
1224
+ if payload['rule'].empty?
1225
+ print_green_success "Nothing to update"
1226
+ exit 1
1227
+ end
1228
+
1229
+ @network_routers_interface.setopts(options)
1230
+ if options[:dry_run]
1231
+ print_dry_run @network_routers_interface.dry.update_firewall_rule(router['id'], rule['id'], payload)
1232
+ return
1233
+ end
1234
+
1235
+ json_response = @network_routers_interface.update_firewall_rule(router['id'], rule['id'], payload)
1236
+
1237
+ if options[:json]
1238
+ print JSON.pretty_generate(json_response), "\n"
1239
+ return
1240
+ end
1241
+ print_green_success "\nUpdated Network Router Firewall Rule #{payload['rule']['name']}\n"
1242
+ _firewall_rule(router['id'], args[1], options)
1243
+ rescue RestClient::Exception => e
1244
+ print_rest_exception(e, options)
1245
+ exit 1
1246
+ end
1247
+ end
1248
+
1249
+ def remove_firewall_rule(args)
1250
+ options = {}
1251
+ query_params = {}
1252
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1253
+ opts.banner = subcommand_usage("[router] [rule]")
1254
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
1255
+ opts.footer = "Delete a network router firewall rule.\n" +
1256
+ "[router] is required. This is the name or id of an existing network router."
1257
+ "[rule] is required. This is the name or id of an existing network router firewall rule."
1258
+ end
1259
+ optparse.parse!(args)
1260
+ if args.count != 2
1261
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1262
+ end
1263
+ connect(options)
1264
+
1265
+ begin
1266
+ router = find_router(args[0])
1267
+ return if !router
1268
+
1269
+ rule = find_firewall_rule(router, args[1])
1270
+
1271
+ if !rule
1272
+ print_red_alert "Firewall rule #{args[1]} not found for router #{router['name']}"
1273
+ exit 1
1274
+ end
1275
+
1276
+ 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)
1277
+ return 9, "aborted command"
1278
+ end
1279
+ @network_routers_interface.setopts(options)
1280
+ if options[:dry_run]
1281
+ print_dry_run @network_routers_interface.dry.destroy_firewall_rule(router['id'], rule['id'])
1282
+ return
1283
+ end
1284
+ json_response = @network_routers_interface.destroy_firewall_rule(router['id'], rule['id'])
1285
+ if options[:json]
1286
+ print JSON.pretty_generate(json_response)
1287
+ print "\n"
1288
+ elsif !options[:quiet]
1289
+ print_green_success "\nFirewall rule #{rule['name']} for router #{router['name']} is being removed...\n"
1290
+ _firewall_rules(find_router(router['id']), options)
1291
+ end
1292
+ rescue RestClient::Exception => e
1293
+ print_rest_exception(e, options)
1294
+ exit 1
1295
+ end
1296
+ end
1297
+
1298
+ def dhcp(args)
1299
+ options = {}
1300
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1301
+ opts.banner = subcommand_usage("[router]")
1302
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
1303
+ opts.footer = "Display network router DHCP details." + "\n" +
1304
+ "[router] is required. This is the name or id of a network router."
1305
+ end
1306
+
1307
+ optparse.parse!(args)
1308
+ connect(options)
1309
+
1310
+ if args.count < 1
1311
+ puts optparse
1312
+ return 1
1313
+ end
1314
+
1315
+ begin
1316
+ @network_routers_interface.setopts(options)
1317
+ if options[:dry_run]
1318
+ if args[0].to_s =~ /\A\d{1,}\Z/
1319
+ print_dry_run @network_routers_interface.dry.get(args[0].to_i)
1320
+ else
1321
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
1322
+ end
1323
+ return
1324
+ end
1325
+ router = find_router(args[0])
1326
+ if router.nil?
1327
+ return 1
1328
+ end
1329
+
1330
+ json_response = {'networkRouter' => router}
1331
+
1332
+ if options[:json]
1333
+ puts as_json(json_response, options, "networkRouter")
1334
+ return 0
1335
+ elsif options[:yaml]
1336
+ puts as_yaml(json_response, options, "networkRouter")
1337
+ return 0
1338
+ elsif options[:csv]
1339
+ puts records_as_csv([json_response['networkRouter']], options)
1340
+ return 0
1341
+ end
1342
+
1343
+ print_h1 "Network Router DHCP Details For: #{router['name']}"
1344
+ print cyan
1345
+
1346
+ if router['type']['hasDhcp']
1347
+ print_dhcp(router, true)
1348
+ else
1349
+ print_red_alert "DHCP not supported for #{router['type']['name']}"
1350
+ end
1351
+ println reset
1352
+ rescue RestClient::Exception => e
1353
+ print_rest_exception(e, options)
1354
+ return 1
1355
+ end
1356
+ end
1357
+
1358
+ def routes(args)
1359
+ options = {}
1360
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1361
+ opts.banner = subcommand_usage("[router]")
1362
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
1363
+ opts.footer = "List network router routes." + "\n" +
1364
+ "[router] is required. This is the name or id of a network router."
1365
+ end
1366
+
1367
+ optparse.parse!(args)
1368
+ connect(options)
1369
+
1370
+ if args.count < 1
1371
+ puts optparse
1372
+ return 1
1373
+ end
1374
+ _routes(args[0], options)
1375
+ end
1376
+
1377
+ def _routes(router_id, options)
1378
+ begin
1379
+ @network_routers_interface.setopts(options)
1380
+ if options[:dry_run]
1381
+ if args[0].to_s =~ /\A\d{1,}\Z/
1382
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
1383
+ else
1384
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
1385
+ end
1386
+ return
1387
+ end
1388
+ router = find_router(router_id)
1389
+ if router.nil?
1390
+ return 1
1391
+ end
1392
+
1393
+ json_response = {'networkRoutes' => router['routes']}
1394
+
1395
+ if options[:json]
1396
+ puts as_json(json_response, options, "networkRoutes")
1397
+ return 0
1398
+ elsif options[:yaml]
1399
+ puts as_yaml(json_response, options, "networkRoutes")
1400
+ return 0
1401
+ elsif options[:csv]
1402
+ puts records_as_csv(json_response['networkRoutes'], options)
1403
+ return 0
1404
+ end
1405
+
1406
+ print_h1 "Network Router Routes For: #{router['name']}"
1407
+ print cyan
1408
+
1409
+ if router['type']['hasRouting']
1410
+ print_routes(router)
1411
+ else
1412
+ print_red_alert "Routes not supported for #{router['type']['name']}"
1413
+ end
1414
+ print reset
1415
+ rescue RestClient::Exception => e
1416
+ print_rest_exception(e, options)
1417
+ return 1
1418
+ end
1419
+ end
1420
+
1421
+ def add_route(args)
1422
+ options = {:options=>{}}
1423
+ params = {}
1424
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
1425
+ opts.banner = subcommand_usage("[router] [name]")
1426
+ opts.on('-n', '--name VALUE', String, "Name for this route") do |val|
1427
+ params['name'] = val
1428
+ end
1429
+ opts.on('-D', '--description VALUE', String, "Description") do |val|
1430
+ params['description'] = val
1431
+ end
1432
+ opts.on('--enabled [on|off]', String, "Can be used to enable / disable the route. Default is on") do |val|
1433
+ options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
1434
+ end
1435
+ opts.on('--default [on|off]', String, "Can be used to enable / disable as default route. Default is off") do |val|
1436
+ options[:defaultRoute] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
1437
+ end
1438
+ opts.on('--source VALUE', String, "Network for this route") do |val|
1439
+ params['source'] = val
1440
+ end
1441
+ opts.on('--destination VALUE', String, "Next hop for this route") do |val|
1442
+ params['destination'] = val
1443
+ end
1444
+ opts.on('--mtu VALUE', String, "MTU for this route") do |val|
1445
+ params['networkMtu'] = val
1446
+ end
1447
+ opts.on('--priority VALUE', Integer, "Priority for this route") do |val|
1448
+ params['priority'] = val
540
1449
  end
541
1450
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
542
- opts.footer = "Create a network router firewall rule."
1451
+ opts.footer = "Create a network router route."
543
1452
  end
544
1453
  optparse.parse!(args)
545
1454
  connect(options)
@@ -558,55 +1467,61 @@ class Morpheus::Cli::NetworkRoutersCommand
558
1467
  return 1
559
1468
  end
560
1469
 
561
- if !router['type']['hasFirewall']
562
- print_red_alert "Firewall not supported for #{router['type']['name']}"
1470
+ if !router['type']['hasRouting']
1471
+ print_red_alert "Routes not supported for #{router['type']['name']}"
563
1472
  return 1
564
1473
  end
565
1474
 
566
1475
  if options[:payload]
567
1476
  payload = options[:payload]
1477
+ payload = {'networkRoute' => payload['route']} if payload['route']
568
1478
  else
569
- params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Rule Name', 'required' => true}], options[:options], @api_client, params)['name']
1479
+ params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], options[:options], @api_client, params)['name']
1480
+ params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false}], options[:options], @api_client, params)['description']
570
1481
 
571
- option_types = router['type']['ruleOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
1482
+ # prompt for enabled if not set
1483
+ 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]
572
1484
 
573
- # prompt options
574
- api_params = {}
575
- api_params['networkServerId'] = router['networkServer']['id'] if router['networkServer']
576
- api_params['zoneId'] = router['zone']['id'] if router['networkServer'].nil?
577
- option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'rule' => ''}}), @api_client, api_params, nil, true)
578
- payload = {'rule' => params.deep_merge(option_result)}
1485
+ # default route
1486
+ 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]
1487
+
1488
+ params['source'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'type' => 'text', 'fieldLabel' => 'Network', 'required' => true}], options[:options], @api_client, params)['source']
1489
+ params['destination'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'type' => 'text', 'fieldLabel' => 'Next Hop', 'required' => true}], options[:options], @api_client, params)['destination']
1490
+ params['networkMtu'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkMtu', 'type' => 'text', 'fieldLabel' => 'MTU', 'required' => false}], options[:options], @api_client, params)['networkMtu']
1491
+ params['priority'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priority', 'type' => 'number', 'fieldLabel' => 'Priority', 'required' => false}], options[:options], @api_client, params)['priority']
1492
+
1493
+ payload = {'networkRoute' => params}
579
1494
  end
580
1495
 
581
1496
  @network_routers_interface.setopts(options)
582
1497
  if options[:dry_run]
583
- print_dry_run @network_routers_interface.dry.create_firewall_rule(router['id'], payload)
1498
+ print_dry_run @network_routers_interface.dry.create_route(router['id'], payload)
584
1499
  return
585
1500
  end
586
1501
 
587
- json_response = @network_routers_interface.create_firewall_rule(router['id'], payload)
1502
+ json_response = @network_routers_interface.create_route(router['id'], payload)
588
1503
 
589
1504
  if options[:json]
590
1505
  print JSON.pretty_generate(json_response), "\n"
591
1506
  return
592
1507
  end
593
- print_green_success "\nAdded Network Router Firewall Rule #{payload['rule']['name']}\n"
594
- _firewall(router['id'], options.merge({:rules_only => true}))
1508
+ print_green_success "\nAdded Network Router Route #{payload['networkRoute']['name']}"
1509
+ _routes(router['id'], options)
595
1510
  rescue RestClient::Exception => e
596
1511
  print_rest_exception(e, options)
597
1512
  exit 1
598
1513
  end
599
1514
  end
600
1515
 
601
- def remove_firewall_rule(args)
1516
+ def remove_route(args)
602
1517
  options = {}
603
1518
  query_params = {}
604
1519
  optparse = Morpheus::Cli::OptionParser.new do |opts|
605
1520
  opts.banner = subcommand_usage("[router] [rule]")
606
1521
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
607
- opts.footer = "Delete a network router firewall rule.\n" +
1522
+ opts.footer = "Delete a network router route.\n" +
608
1523
  "[router] is required. This is the name or id of an existing network router."
609
- "[rule] is required. This is the name or id of an existing network router firewall rule."
1524
+ "[route] is required. This is the name or id of an existing network router route."
610
1525
  end
611
1526
  optparse.parse!(args)
612
1527
  if args.count != 2
@@ -618,28 +1533,28 @@ class Morpheus::Cli::NetworkRoutersCommand
618
1533
  router = find_router(args[0])
619
1534
  return if !router
620
1535
 
621
- rule = router['firewall'] && router['firewall']['rules'] ? router['firewall']['rules'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
1536
+ route = router['routes'] ? router['routes'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
622
1537
 
623
- if !rule
624
- print_red_alert "Firewall rule #{args[1]} not found for router #{router['name']}"
1538
+ if !route
1539
+ print_red_alert "Route #{args[1]} not found for router #{router['name']}"
625
1540
  exit 1
626
1541
  end
627
1542
 
628
- 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)
1543
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the route '#{route['name']}' from router '#{router['name']}'?", options)
629
1544
  return 9, "aborted command"
630
1545
  end
631
1546
  @network_routers_interface.setopts(options)
632
1547
  if options[:dry_run]
633
- print_dry_run @network_routers_interface.dry.destroy_firewall_rule(router['id'], rule['id'])
1548
+ print_dry_run @network_routers_interface.dry.destroy_route(router['id'], route['id'])
634
1549
  return
635
1550
  end
636
- json_response = @network_routers_interface.destroy_firewall_rule(router['id'], rule['id'])
1551
+ json_response = @network_routers_interface.destroy_route(router['id'], route['id'])
637
1552
  if options[:json]
638
1553
  print JSON.pretty_generate(json_response)
639
1554
  print "\n"
640
1555
  elsif !options[:quiet]
641
- print_green_success "\nFirewall rule #{rule['name']} for router #{router['name']} is being removed...\n"
642
- _firewall(router['id'], options.merge({:rules_only => true}))
1556
+ print_green_success "\nRoute #{route['name']} for router #{router['name']} is being removed..."
1557
+ _routes(router['id'], options)
643
1558
  end
644
1559
  rescue RestClient::Exception => e
645
1560
  print_rest_exception(e, options)
@@ -647,13 +1562,13 @@ class Morpheus::Cli::NetworkRoutersCommand
647
1562
  end
648
1563
  end
649
1564
 
650
- def dhcp(args)
1565
+ def nats(args)
651
1566
  options = {}
652
1567
  optparse = Morpheus::Cli::OptionParser.new do |opts|
653
1568
  opts.banner = subcommand_usage("[router]")
654
1569
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
655
- opts.footer = "Display network router DHCP details." + "\n" +
656
- "[router] is required. This is the name or id of a network router."
1570
+ opts.footer = "List network router NATs." + "\n" +
1571
+ "[router] is required. This is the name or id of a network router."
657
1572
  end
658
1573
 
659
1574
  optparse.parse!(args)
@@ -663,144 +1578,141 @@ class Morpheus::Cli::NetworkRoutersCommand
663
1578
  puts optparse
664
1579
  return 1
665
1580
  end
1581
+ _nats(args[0], options)
1582
+ end
666
1583
 
1584
+ def _nats(router_id, options)
667
1585
  begin
668
1586
  @network_routers_interface.setopts(options)
669
1587
  if options[:dry_run]
670
1588
  if args[0].to_s =~ /\A\d{1,}\Z/
671
- print_dry_run @network_routers_interface.dry.get(args[0].to_i)
1589
+ print_dry_run @network_routers_interface.dry.get(router_id.to_i)
672
1590
  else
673
- print_dry_run @network_routers_interface.dry.list({name:args[0]})
1591
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
674
1592
  end
675
1593
  return
676
1594
  end
677
- router = find_router(args[0])
1595
+ router = find_router(router_id)
678
1596
  if router.nil?
679
1597
  return 1
680
1598
  end
681
1599
 
682
- json_response = {'networkRouter' => router}
1600
+ json_response = {'networkRouterNATs' => router['nats']}
683
1601
 
684
1602
  if options[:json]
685
- puts as_json(json_response, options, "networkRouter")
1603
+ puts as_json(json_response, options, "networkRouterNATs")
686
1604
  return 0
687
1605
  elsif options[:yaml]
688
- puts as_yaml(json_response, options, "networkRouter")
1606
+ puts as_yaml(json_response, options, "networkRouterNATs")
689
1607
  return 0
690
1608
  elsif options[:csv]
691
- puts records_as_csv([json_response['networkRouter']], options)
1609
+ puts records_as_csv(json_response['networkRouterNATs'], options)
692
1610
  return 0
693
1611
  end
694
1612
 
695
- print_h1 "Network Router DHCP Details for: #{router['name']}"
1613
+ print_h1 "Network Router NATs For: #{router['name']}"
696
1614
  print cyan
697
1615
 
698
- if router['type']['hasDhcp']
699
- print_dhcp(router, true)
1616
+ if router['type']['hasNat']
1617
+ print_nats(router)
700
1618
  else
701
- print_red_alert "DHCP not supported for #{router['type']['name']}"
1619
+ print_red_alert "NATs not supported for #{router['type']['name']}"
702
1620
  end
703
- println reset
1621
+ print reset
704
1622
  rescue RestClient::Exception => e
705
1623
  print_rest_exception(e, options)
706
1624
  return 1
707
1625
  end
708
1626
  end
709
1627
 
710
- def routes(args)
1628
+ def nat(args)
711
1629
  options = {}
712
1630
  optparse = Morpheus::Cli::OptionParser.new do |opts|
713
- opts.banner = subcommand_usage("[router]")
1631
+ opts.banner = subcommand_usage("[router] [rule]")
714
1632
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
715
- opts.footer = "List network router routes." + "\n" +
716
- "[router] is required. This is the name or id of a network router."
1633
+ opts.footer = "Display network router firewall rule details." + "\n" +
1634
+ "[router] is required. This is the name or id of a network router.\n" +
1635
+ "[rule] is required. This is the name or id of a firewall rule.\n"
717
1636
  end
718
1637
 
719
1638
  optparse.parse!(args)
720
1639
  connect(options)
721
1640
 
722
- if args.count < 1
1641
+ if args.count < 2
723
1642
  puts optparse
724
1643
  return 1
725
1644
  end
726
- _routes(args[0], options)
727
- end
728
1645
 
729
- def _routes(router_id, options)
730
1646
  begin
731
1647
  @network_routers_interface.setopts(options)
732
1648
  if options[:dry_run]
733
1649
  if args[0].to_s =~ /\A\d{1,}\Z/
734
- print_dry_run @network_routers_interface.dry.get(router_id.to_i)
1650
+ print_dry_run @network_routers_interface.dry.get(args[0].to_i)
735
1651
  else
736
- print_dry_run @network_routers_interface.dry.list({name:router_id})
1652
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
737
1653
  end
738
1654
  return
739
1655
  end
740
- router = find_router(router_id)
1656
+ router = find_router(args[0])
741
1657
  if router.nil?
742
1658
  return 1
743
1659
  end
744
1660
 
745
- json_response = {'networkRouter' => router}
1661
+ if router['type']['hasNat']
1662
+ nat = (router['nats'] || []).find {|it| it['id'] == args[1].to_i || it['name'] == args[1]}
746
1663
 
747
- if options[:json]
748
- puts as_json(json_response, options, "networkRouter")
749
- return 0
750
- elsif options[:yaml]
751
- puts as_yaml(json_response, options, "networkRouter")
752
- return 0
753
- elsif options[:csv]
754
- puts records_as_csv([json_response['networkRouter']], options)
755
- return 0
756
- end
1664
+ if nat
1665
+ json_response = {'networkRouterNAT' => nat}
757
1666
 
758
- print_h1 "Network Router Routes for: #{router['name']}"
759
- print cyan
1667
+ if options[:json]
1668
+ puts as_json(json_response, options, "networkRouterNAT")
1669
+ return 0
1670
+ elsif options[:yaml]
1671
+ puts as_yaml(json_response, options, "networkRouterNAT")
1672
+ return 0
1673
+ elsif options[:csv]
1674
+ puts records_as_csv([json_response['networkRouterNAT']], options)
1675
+ return 0
1676
+ end
760
1677
 
761
- if router['type']['hasRouting']
762
- print_routes(router)
1678
+ print_h1 "Network Router NAT Details"
1679
+ print cyan
1680
+
1681
+ description_cols = {
1682
+ "ID" => lambda {|it| it['id'] },
1683
+ "Name" => lambda {|it| it['name'] },
1684
+ "Description" => lambda {|it| it['description'] },
1685
+ "Enabled" => lambda {|it| format_boolean(it['enabled'])},
1686
+ "Source Network" => lambda {|it| it['sourceNetwork']},
1687
+ "Destination Network" => lambda {|it| it['destinationNetwork']},
1688
+ "Translated Network" => lambda {|it| it['translatedNetwork']},
1689
+ "Translated Port" => lambda {|it| it['translatedPorts']},
1690
+ "Priority" => lambda {|it| it['priority'] }
1691
+ }
1692
+ print_description_list(description_cols, nat)
1693
+ else
1694
+ print_red_alert "NAT #{args[1]} not found for router #{router['name']}"
1695
+ end
763
1696
  else
764
- print_red_alert "Routes not supported for #{router['type']['name']}"
1697
+ print_red_alert "NATs not supported for #{router['type']['name']}"
765
1698
  end
766
- print reset
1699
+ println reset
767
1700
  rescue RestClient::Exception => e
768
1701
  print_rest_exception(e, options)
769
1702
  return 1
770
1703
  end
771
1704
  end
772
1705
 
773
- def add_route(args)
1706
+ def add_nat(args)
774
1707
  options = {:options=>{}}
775
1708
  params = {}
776
1709
  optparse = Morpheus::Cli::OptionParser.new do|opts|
777
1710
  opts.banner = subcommand_usage("[router] [name]")
778
- opts.on('-n', '--name VALUE', String, "Name for this route") do |val|
1711
+ opts.on('-n', '--name VALUE', String, "Name for this NAT") do |val|
779
1712
  params['name'] = val
780
1713
  end
781
- opts.on('-D', '--description VALUE', String, "Description") do |val|
782
- params['description'] = val
783
- end
784
- opts.on('--enabled [on|off]', String, "Can be used to enable / disable the route. Default is on") do |val|
785
- options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
786
- end
787
- opts.on('--default [on|off]', String, "Can be used to enable / disable as default route. Default is off") do |val|
788
- options[:defaultRoute] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
789
- end
790
- opts.on('--source VALUE', String, "Network for this route") do |val|
791
- params['source'] = val
792
- end
793
- opts.on('--destination VALUE', String, "Next hop for this route") do |val|
794
- params['destination'] = val
795
- end
796
- opts.on('--mtu VALUE', String, "MTU for this route") do |val|
797
- params['networkMtu'] = val
798
- end
799
- opts.on('--priority VALUE', Integer, "Priority for this route") do |val|
800
- params['priority'] = val
801
- end
802
1714
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
803
- opts.footer = "Create a network router route."
1715
+ opts.footer = "Create a network router NAT."
804
1716
  end
805
1717
  optparse.parse!(args)
806
1718
  connect(options)
@@ -819,8 +1731,8 @@ class Morpheus::Cli::NetworkRoutersCommand
819
1731
  return 1
820
1732
  end
821
1733
 
822
- if !router['type']['hasRouting']
823
- print_red_alert "Routes not supported for #{router['type']['name']}"
1734
+ if !router['type']['hasNat']
1735
+ print_red_alert "NATs not supported for #{router['type']['name']}"
824
1736
  return 1
825
1737
  end
826
1738
 
@@ -828,51 +1740,108 @@ class Morpheus::Cli::NetworkRoutersCommand
828
1740
  payload = options[:payload]
829
1741
  else
830
1742
  params['name'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], options[:options], @api_client, params)['name']
831
- params['description'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false}], options[:options], @api_client, params)['description']
832
1743
 
833
- # prompt for enabled if not set
834
- 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]
1744
+ option_types = router['type']['natOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
835
1745
 
836
- # default route
837
- 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]
1746
+ # prompt options
1747
+ option_result = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options].deep_merge({:context_map => {'nat' => ''}}), @api_client, {'networkServer' => {'id' => router['networkServer']['id']}}, nil, true)
1748
+ payload = {'networkRouterNAT' => params.deep_merge(option_result)}
1749
+ end
838
1750
 
839
- params['source'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'type' => 'text', 'fieldLabel' => 'Network', 'required' => true}], options[:options], @api_client, params)['source']
840
- params['destination'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'type' => 'text', 'fieldLabel' => 'Next Hop', 'required' => true}], options[:options], @api_client, params)['destination']
841
- params['networkMtu'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'networkMtu', 'type' => 'text', 'fieldLabel' => 'MTU', 'required' => false}], options[:options], @api_client, params)['networkMtu']
842
- params['priority'] ||= Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priority', 'type' => 'number', 'fieldLabel' => 'Priority', 'required' => false}], options[:options], @api_client, params)['priority']
1751
+ @network_routers_interface.setopts(options)
1752
+ if options[:dry_run]
1753
+ print_dry_run @network_routers_interface.dry.create_nat(router['id'], payload)
1754
+ return
1755
+ end
1756
+
1757
+ json_response = @network_routers_interface.create_nat(router['id'], payload)
1758
+
1759
+ if options[:json]
1760
+ print JSON.pretty_generate(json_response), "\n"
1761
+ return
1762
+ end
1763
+ print_green_success "\nAdded Network Router NAT #{payload['networkRouterNAT']['name']}\n"
1764
+ _nats(router['id'], options)
1765
+ rescue RestClient::Exception => e
1766
+ print_rest_exception(e, options)
1767
+ exit 1
1768
+ end
1769
+ end
1770
+
1771
+ def update_nat(args)
1772
+ options = {:options=>{}}
1773
+ params = {}
1774
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
1775
+ opts.banner = subcommand_usage("[router] [NAT]")
1776
+ opts.on('-n', '--name VALUE', String, "Name for this NAT") do |val|
1777
+ params['name'] = val
1778
+ end
1779
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1780
+ opts.footer = "Update a network router NAT.\n" +
1781
+ "[router] is required. This is the name or id of an existing network router.\n" +
1782
+ "[NAT] is required. This is the name or id of an existing network router NAT."
1783
+ end
1784
+ optparse.parse!(args)
1785
+ if args.count != 2
1786
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1787
+ end
1788
+ connect(options)
1789
+ begin
1790
+ router = find_router(args[0])
1791
+
1792
+ if router.nil?
1793
+ return 1
1794
+ end
1795
+
1796
+ if !router['type']['hasNat']
1797
+ print_red_alert "NATs not supported for #{router['type']['name']}"
1798
+ return 1
1799
+ end
1800
+
1801
+ nat = router['firewall'] && router['nats'] ? router['nats'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
1802
+
1803
+ if !nat
1804
+ print_red_alert "NAT #{args[1]} not found for router #{router['name']}"
1805
+ exit 1
1806
+ end
1807
+
1808
+ payload = parse_payload(options) || {'networkRouterNAT' => params}
1809
+ payload['networkRouterNAT'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] && !payload['networkRouterNAT'].nil?
843
1810
 
844
- payload = {'route' => params}
1811
+ if payload['networkRouterNAT'].empty?
1812
+ print_green_success "Nothing to update"
1813
+ exit 1
845
1814
  end
846
1815
 
847
1816
  @network_routers_interface.setopts(options)
848
1817
  if options[:dry_run]
849
- print_dry_run @network_routers_interface.dry.create_route(router['id'], payload)
1818
+ print_dry_run @network_routers_interface.dry.update_nat(router['id'], nat['id'], payload)
850
1819
  return
851
1820
  end
852
1821
 
853
- json_response = @network_routers_interface.create_route(router['id'], payload)
1822
+ json_response = @network_routers_interface.update_nat(router['id'], nat['id'], payload)
854
1823
 
855
1824
  if options[:json]
856
1825
  print JSON.pretty_generate(json_response), "\n"
857
1826
  return
858
1827
  end
859
- print_green_success "\nAdded Network Router Route #{payload['route']['name']}"
860
- _routes(router['id'], options)
1828
+ print_green_success "\nUpdated Network Router NAT #{nat['name']}\n"
1829
+ _nats(router['id'], options)
861
1830
  rescue RestClient::Exception => e
862
1831
  print_rest_exception(e, options)
863
1832
  exit 1
864
1833
  end
865
1834
  end
866
1835
 
867
- def remove_route(args)
1836
+ def remove_nat(args)
868
1837
  options = {}
869
1838
  query_params = {}
870
1839
  optparse = Morpheus::Cli::OptionParser.new do |opts|
871
- opts.banner = subcommand_usage("[router] [rule]")
1840
+ opts.banner = subcommand_usage("[router] [NAT]")
872
1841
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
873
- opts.footer = "Delete a network router route.\n" +
874
- "[router] is required. This is the name or id of an existing network router."
875
- "[route] is required. This is the name or id of an existing network router route."
1842
+ opts.footer = "Delete a network router NAT.\n" +
1843
+ "[router] is required. This is the name or id of an existing network router."
1844
+ "[NAT] is required. This is the name or id of an existing network router NAT."
876
1845
  end
877
1846
  optparse.parse!(args)
878
1847
  if args.count != 2
@@ -884,28 +1853,33 @@ class Morpheus::Cli::NetworkRoutersCommand
884
1853
  router = find_router(args[0])
885
1854
  return if !router
886
1855
 
887
- route = router['routes'] ? router['routes'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
1856
+ if !router['type']['hasNat']
1857
+ print_red_alert "NATs not supported for #{router['type']['name']}"
1858
+ return 1
1859
+ end
888
1860
 
889
- if !route
890
- print_red_alert "Route #{args[1]} not found for router #{router['name']}"
1861
+ nat = router['nats'] ? router['nats'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
1862
+
1863
+ if !nat
1864
+ print_red_alert "NAT #{args[1]} not found for router #{router['name']}"
891
1865
  exit 1
892
1866
  end
893
1867
 
894
- unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the route '#{route['name']}' from router '#{router['name']}'?", options)
1868
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the NAT '#{nat['name']}' from router '#{router['name']}'?", options)
895
1869
  return 9, "aborted command"
896
1870
  end
897
1871
  @network_routers_interface.setopts(options)
898
1872
  if options[:dry_run]
899
- print_dry_run @network_routers_interface.dry.destroy_route(router['id'], route['id'])
1873
+ print_dry_run @network_routers_interface.dry.destroy_nat(router['id'], nat['id'])
900
1874
  return
901
1875
  end
902
- json_response = @network_routers_interface.destroy_route(router['id'], route['id'])
1876
+ json_response = @network_routers_interface.destroy_nat(router['id'], nat['id'])
903
1877
  if options[:json]
904
1878
  print JSON.pretty_generate(json_response)
905
1879
  print "\n"
906
1880
  elsif !options[:quiet]
907
- print_green_success "\nRoute #{route['name']} for router #{router['name']} is being removed..."
908
- _routes(router['id'], options)
1881
+ print_green_success "\nNAT #{nat['name']} for router #{router['name']} is being removed...\n"
1882
+ _nats(router['id'], options)
909
1883
  end
910
1884
  rescue RestClient::Exception => e
911
1885
  print_rest_exception(e, options)
@@ -998,7 +1972,7 @@ class Morpheus::Cli::NetworkRoutersCommand
998
1972
  return
999
1973
  end
1000
1974
 
1001
- print_h1 "Network Router Type Details for: #{router_type['name']}"
1975
+ print_h1 "Network Router Type Details For: #{router_type['name']}"
1002
1976
  print cyan
1003
1977
 
1004
1978
  description_cols = {
@@ -1015,12 +1989,14 @@ class Morpheus::Cli::NetworkRoutersCommand
1015
1989
  }
1016
1990
  print_description_list(description_cols, router_type)
1017
1991
 
1018
- if router_type['optionTypes'].count > 0
1019
- println cyan
1020
- print Morpheus::Cli::OptionTypes.display_option_types_help(
1021
- router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName'])},
1022
- {:include_context => true, :context_map => {'networkRouter' => ''}, :color => cyan, :title => "Available Router Options"}
1023
- )
1992
+ {'optionTypes' => 'Router', 'ruleOptionTypes' => 'Firewall Rule', 'ruleGroupOptionTypes' => 'Firewall Rule Group', 'natOptionTypes' => 'NAT'}.each_pair do |field, title|
1993
+ if !router_type[field].nil? && router_type[field].count > 0
1994
+ println cyan
1995
+ print Morpheus::Cli::OptionTypes.display_option_types_help(
1996
+ router_type[field].reject {|it| ['enabled'].include?(it['fieldName'])},
1997
+ {:include_context => true, :context_map => {'networkRouter' => ''}, :color => cyan, :title => "Available #{title} Options"}
1998
+ )
1999
+ end
1024
2000
  end
1025
2001
  print reset
1026
2002
  return 0
@@ -1092,10 +2068,10 @@ class Morpheus::Cli::NetworkRoutersCommand
1092
2068
 
1093
2069
  private
1094
2070
 
1095
- def print_firewall(router, details=false, rules_only=false)
2071
+ def print_firewall(router, options = {}) #details=false, rules_only=false, rule_groups_only=false)
1096
2072
  if router['type']['hasFirewall']
1097
2073
  if router['firewall']
1098
- if details
2074
+ if options[:details]
1099
2075
  description_cols = {
1100
2076
  "Network Router" => lambda {|it| it['name'] },
1101
2077
  "Enabled" => lambda {|it| format_boolean(it['firewall']['enabled'])},
@@ -1106,28 +2082,10 @@ class Morpheus::Cli::NetworkRoutersCommand
1106
2082
  description_cols[k.gsub(/[A-Z]/, ' \0').downcase] = lambda {|it| it['firewall']['global'][k]}
1107
2083
  end
1108
2084
 
1109
- if !rules_only
1110
- print_description_list(description_cols, router)
1111
- print_h2 "Firewall Rules"
1112
- end
2085
+ print_description_list(description_cols, router)
1113
2086
 
1114
- if (router['firewall']['rules'] || []).count > 0
1115
- rows = router['firewall']['rules'].collect do |it|
1116
- {
1117
- id: it['id'],
1118
- name: it['name'],
1119
- type: it['ruleType'],
1120
- policy: it['policy'],
1121
- direction: it['direction'] || 'any',
1122
- source: it['source'] || 'any',
1123
- destination: it['destination'] || 'any',
1124
- application: it['applications'].count > 0 ? it['applications'][0]['name'] : "#{(it['protocol'] || 'any')} #{it['portRange'] || ''}"
1125
- }
1126
- end
1127
- puts as_pretty_table(rows, [:id, :name, :type, :policy, :direction, :source, :destination, :application])
1128
- else
1129
- println "No firewall rules"
1130
- end
2087
+ _firewall_rule_groups(router, options) if router['type']['hasFirewallGroups']
2088
+ _firewall_rules(router, options) if router['type']['hasFirewall']
1131
2089
  else
1132
2090
  print "Enabled: #{format_boolean(router['firewall']['enabled'])}".center(20)
1133
2091
  print "Version: #{router['firewall']['version']}".center(20)
@@ -1209,6 +2167,26 @@ class Morpheus::Cli::NetworkRoutersCommand
1209
2167
  end
1210
2168
  end
1211
2169
 
2170
+ def print_nats(router)
2171
+ if router['type']['hasNat']
2172
+ if router['nats'].count > 0
2173
+ rows = router['nats'].collect do |it|
2174
+ {
2175
+ id: it['id'],
2176
+ name: it['name'],
2177
+ description: it['description'],
2178
+ source_network: it['sourceNetwork'],
2179
+ destination_network: it['destinationNetwork'],
2180
+ translated_network: it['translatedNetwork']
2181
+ }
2182
+ end
2183
+ puts as_pretty_table(rows, [:id, :name, :description, :source_network, :destination_network, :translated_network])
2184
+ else
2185
+ println "No NATs\n"
2186
+ end
2187
+ end
2188
+ end
2189
+
1212
2190
  def format_router_status(router, return_color = cyan)
1213
2191
  status = router['status']
1214
2192
  color = white
@@ -1227,7 +2205,9 @@ class Morpheus::Cli::NetworkRoutersCommand
1227
2205
  if val.to_s =~ /\A\d{1,}\Z/
1228
2206
  return find_router_by_id(val)
1229
2207
  else
1230
- return find_router_by_name(val)
2208
+ if router = find_router_by_name(val)
2209
+ return find_router_by_id(router['id'])
2210
+ end
1231
2211
  end
1232
2212
  end
1233
2213
 
@@ -1291,4 +2271,22 @@ class Morpheus::Cli::NetworkRoutersCommand
1291
2271
  services = @network_services_interface.list()['networkServices']
1292
2272
  (val.to_s =~ /\A\d{1,}\Z/) ? services.find {|it| it['id'].to_i == val.to_i} : services.find {|it| it['name'] == val}
1293
2273
  end
2274
+
2275
+ def find_firewall_rule(router, rule_id)
2276
+ rule = nil
2277
+ if router['type']['hasFirewallGroups']
2278
+ if router['firewall'] && router['firewall']['ruleGroups']
2279
+ router['firewall']['ruleGroups'].each do |group|
2280
+ if !rule && group['rules']
2281
+ if rule = group['rules'].find { |it| it['name'] == rule_id || it['id'] == rule_id.to_i }
2282
+ rule['groupId'] = group['id']
2283
+ end
2284
+ end
2285
+ end
2286
+ end
2287
+ else
2288
+ rule = router['firewall'] && router['firewall']['rules'] ? router['firewall']['rules'].find {|it| it['name'] == args[1] || it['id'] == args[1].to_i} : nil
2289
+ end
2290
+ rule
2291
+ end
1294
2292
  end