morpheus-cli 5.3.0.3 → 5.3.2.1

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 (199) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +1 -3
  4. data/lib/morpheus/api/account_groups_interface.rb +0 -6
  5. data/lib/morpheus/api/accounts_interface.rb +4 -36
  6. data/lib/morpheus/api/api_client.rb +167 -119
  7. data/lib/morpheus/api/appliance_settings_interface.rb +6 -9
  8. data/lib/morpheus/api/approvals_interface.rb +5 -8
  9. data/lib/morpheus/api/apps_interface.rb +0 -7
  10. data/lib/morpheus/api/archive_buckets_interface.rb +9 -16
  11. data/lib/morpheus/api/archive_files_interface.rb +0 -6
  12. data/lib/morpheus/api/auth_interface.rb +4 -4
  13. data/lib/morpheus/api/backup_settings_interface.rb +5 -8
  14. data/lib/morpheus/api/blueprints_interface.rb +1 -7
  15. data/lib/morpheus/api/budgets_interface.rb +0 -6
  16. data/lib/morpheus/api/certificate_types_interface.rb +14 -0
  17. data/lib/morpheus/api/certificates_interface.rb +9 -0
  18. data/lib/morpheus/api/cloud_datastores_interface.rb +0 -6
  19. data/lib/morpheus/api/cloud_folders_interface.rb +1 -7
  20. data/lib/morpheus/api/cloud_policies_interface.rb +0 -6
  21. data/lib/morpheus/api/cloud_resource_pools_interface.rb +0 -6
  22. data/lib/morpheus/api/clouds_interface.rb +0 -6
  23. data/lib/morpheus/api/clusters_interface.rb +39 -42
  24. data/lib/morpheus/api/containers_interface.rb +0 -6
  25. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -6
  26. data/lib/morpheus/api/cypher_interface.rb +0 -6
  27. data/lib/morpheus/api/datastores_interface.rb +4 -7
  28. data/lib/morpheus/api/deploy_interface.rb +1 -6
  29. data/lib/morpheus/api/environments_interface.rb +0 -6
  30. data/lib/morpheus/api/execute_schedules_interface.rb +0 -6
  31. data/lib/morpheus/api/execution_request_interface.rb +0 -6
  32. data/lib/morpheus/api/file_copy_request_interface.rb +2 -9
  33. data/lib/morpheus/api/group_policies_interface.rb +0 -6
  34. data/lib/morpheus/api/groups_interface.rb +0 -7
  35. data/lib/morpheus/api/guidance_interface.rb +9 -12
  36. data/lib/morpheus/api/health_interface.rb +0 -6
  37. data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +0 -6
  38. data/lib/morpheus/api/image_builder_image_builds_interface.rb +0 -6
  39. data/lib/morpheus/api/image_builder_interface.rb +3 -9
  40. data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +0 -6
  41. data/lib/morpheus/api/instance_types_interface.rb +0 -7
  42. data/lib/morpheus/api/instances_interface.rb +8 -19
  43. data/lib/morpheus/api/integration_types_interface.rb +14 -0
  44. data/lib/morpheus/api/integrations_interface.rb +36 -21
  45. data/lib/morpheus/api/invoice_line_items_interface.rb +4 -9
  46. data/lib/morpheus/api/jobs_interface.rb +11 -14
  47. data/lib/morpheus/api/key_pairs_interface.rb +0 -6
  48. data/lib/morpheus/api/library_cluster_layouts_interface.rb +0 -6
  49. data/lib/morpheus/api/library_container_scripts_interface.rb +0 -6
  50. data/lib/morpheus/api/library_container_templates_interface.rb +0 -6
  51. data/lib/morpheus/api/library_container_types_interface.rb +0 -6
  52. data/lib/morpheus/api/library_container_upgrades_interface.rb +0 -6
  53. data/lib/morpheus/api/library_instance_types_interface.rb +0 -6
  54. data/lib/morpheus/api/library_layouts_interface.rb +0 -6
  55. data/lib/morpheus/api/library_spec_template_types_interface.rb +0 -6
  56. data/lib/morpheus/api/library_spec_templates_interface.rb +0 -6
  57. data/lib/morpheus/api/license_interface.rb +0 -6
  58. data/lib/morpheus/api/load_balancer_pools_interface.rb +9 -0
  59. data/lib/morpheus/api/load_balancer_types_interface.rb +9 -0
  60. data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +9 -0
  61. data/lib/morpheus/api/load_balancers_interface.rb +4 -59
  62. data/lib/morpheus/api/log_settings_interface.rb +9 -12
  63. data/lib/morpheus/api/logs_interface.rb +0 -6
  64. data/lib/morpheus/api/monitoring_alerts_interface.rb +0 -6
  65. data/lib/morpheus/api/monitoring_apps_interface.rb +0 -6
  66. data/lib/morpheus/api/monitoring_checks_interface.rb +0 -6
  67. data/lib/morpheus/api/monitoring_contacts_interface.rb +0 -6
  68. data/lib/morpheus/api/monitoring_groups_interface.rb +0 -6
  69. data/lib/morpheus/api/monitoring_incidents_interface.rb +0 -6
  70. data/lib/morpheus/api/monitoring_interface.rb +6 -12
  71. data/lib/morpheus/api/network_domain_records_interface.rb +0 -6
  72. data/lib/morpheus/api/network_domains_interface.rb +0 -6
  73. data/lib/morpheus/api/network_groups_interface.rb +0 -6
  74. data/lib/morpheus/api/network_pool_ips_interface.rb +0 -6
  75. data/lib/morpheus/api/network_pool_servers_interface.rb +0 -6
  76. data/lib/morpheus/api/network_pools_interface.rb +0 -6
  77. data/lib/morpheus/api/network_proxies_interface.rb +0 -6
  78. data/lib/morpheus/api/network_routers_interface.rb +56 -6
  79. data/lib/morpheus/api/network_security_servers_interface.rb +6 -9
  80. data/lib/morpheus/api/network_services_interface.rb +14 -14
  81. data/lib/morpheus/api/network_subnets_interface.rb +0 -6
  82. data/lib/morpheus/api/network_types_interface.rb +1 -7
  83. data/lib/morpheus/api/networks_interface.rb +0 -6
  84. data/lib/morpheus/api/option_type_lists_interface.rb +18 -12
  85. data/lib/morpheus/api/option_types_interface.rb +0 -6
  86. data/lib/morpheus/api/options_interface.rb +0 -6
  87. data/lib/morpheus/api/packages_interface.rb +0 -6
  88. data/lib/morpheus/api/policies_interface.rb +1 -8
  89. data/lib/morpheus/api/power_schedules_interface.rb +0 -6
  90. data/lib/morpheus/api/price_sets_interface.rb +8 -11
  91. data/lib/morpheus/api/prices_interface.rb +12 -15
  92. data/lib/morpheus/api/processes_interface.rb +0 -6
  93. data/lib/morpheus/api/provision_types_interface.rb +0 -6
  94. data/lib/morpheus/api/provisioning_license_types_interface.rb +0 -6
  95. data/lib/morpheus/api/provisioning_licenses_interface.rb +0 -6
  96. data/lib/morpheus/api/provisioning_settings_interface.rb +6 -9
  97. data/lib/morpheus/api/read_interface.rb +23 -0
  98. data/lib/morpheus/api/reports_interface.rb +0 -6
  99. data/lib/morpheus/api/rest_interface.rb +12 -10
  100. data/lib/morpheus/api/roles_interface.rb +7 -6
  101. data/lib/morpheus/api/secondary_read_interface.rb +25 -0
  102. data/lib/morpheus/api/secondary_rest_interface.rb +42 -0
  103. data/lib/morpheus/api/security_group_rules_interface.rb +0 -7
  104. data/lib/morpheus/api/security_groups_interface.rb +0 -6
  105. data/lib/morpheus/api/server_types_interface.rb +0 -6
  106. data/lib/morpheus/api/servers_interface.rb +7 -6
  107. data/lib/morpheus/api/service_plans_interface.rb +11 -14
  108. data/lib/morpheus/api/storage_providers_interface.rb +9 -16
  109. data/lib/morpheus/api/subnet_types_interface.rb +1 -7
  110. data/lib/morpheus/api/subnets_interface.rb +0 -6
  111. data/lib/morpheus/api/task_sets_interface.rb +0 -6
  112. data/lib/morpheus/api/tasks_interface.rb +0 -6
  113. data/lib/morpheus/api/user_groups_interface.rb +0 -6
  114. data/lib/morpheus/api/user_settings_interface.rb +38 -18
  115. data/lib/morpheus/api/user_sources_interface.rb +0 -6
  116. data/lib/morpheus/api/users_interface.rb +0 -6
  117. data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
  118. data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
  119. data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
  120. data/lib/morpheus/api/vdi_interface.rb +28 -0
  121. data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
  122. data/lib/morpheus/api/virtual_images_interface.rb +0 -6
  123. data/lib/morpheus/api/whitelabel_settings_interface.rb +8 -11
  124. data/lib/morpheus/api/wiki_interface.rb +0 -6
  125. data/lib/morpheus/cli.rb +10 -2
  126. data/lib/morpheus/cli/access_token_command.rb +1 -1
  127. data/lib/morpheus/cli/account_groups_command.rb +4 -4
  128. data/lib/morpheus/cli/apps.rb +68 -84
  129. data/lib/morpheus/cli/archives_command.rb +5 -5
  130. data/lib/morpheus/cli/blueprints_command.rb +5 -5
  131. data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
  132. data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
  133. data/lib/morpheus/cli/certificates_command.rb +575 -0
  134. data/lib/morpheus/cli/change_password_command.rb +4 -4
  135. data/lib/morpheus/cli/cli_command.rb +72 -16
  136. data/lib/morpheus/cli/clouds.rb +3 -2
  137. data/lib/morpheus/cli/clusters.rb +3 -3
  138. data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
  139. data/lib/morpheus/cli/credentials.rb +4 -11
  140. data/lib/morpheus/cli/environments_command.rb +1 -1
  141. data/lib/morpheus/cli/execute_schedules_command.rb +3 -3
  142. data/lib/morpheus/cli/hosts.rb +253 -232
  143. data/lib/morpheus/cli/image_builder_command.rb +6 -6
  144. data/lib/morpheus/cli/instance_types.rb +1 -1
  145. data/lib/morpheus/cli/instances.rb +229 -219
  146. data/lib/morpheus/cli/integrations_command.rb +1155 -42
  147. data/lib/morpheus/cli/invoices_command.rb +75 -67
  148. data/lib/morpheus/cli/key_pairs.rb +2 -2
  149. data/lib/morpheus/cli/library_cluster_layouts_command.rb +2 -3
  150. data/lib/morpheus/cli/library_container_scripts_command.rb +4 -5
  151. data/lib/morpheus/cli/library_container_templates_command.rb +5 -1
  152. data/lib/morpheus/cli/library_container_types_command.rb +8 -9
  153. data/lib/morpheus/cli/library_instance_types_command.rb +6 -7
  154. data/lib/morpheus/cli/library_layouts_command.rb +9 -5
  155. data/lib/morpheus/cli/library_option_lists_command.rb +72 -20
  156. data/lib/morpheus/cli/library_option_types_command.rb +8 -4
  157. data/lib/morpheus/cli/library_spec_templates_command.rb +3 -4
  158. data/lib/morpheus/cli/library_upgrades_command.rb +6 -6
  159. data/lib/morpheus/cli/license.rb +2 -2
  160. data/lib/morpheus/cli/load_balancer_types.rb +37 -0
  161. data/lib/morpheus/cli/load_balancers.rb +149 -314
  162. data/lib/morpheus/cli/log_settings_command.rb +7 -3
  163. data/lib/morpheus/cli/login.rb +10 -1
  164. data/lib/morpheus/cli/mixins/load_balancers_helper.rb +156 -0
  165. data/lib/morpheus/cli/mixins/print_helper.rb +44 -18
  166. data/lib/morpheus/cli/mixins/provisioning_helper.rb +4 -4
  167. data/lib/morpheus/cli/mixins/rest_command.rb +657 -0
  168. data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
  169. data/lib/morpheus/cli/network_routers_command.rb +1187 -176
  170. data/lib/morpheus/cli/networks_command.rb +195 -102
  171. data/lib/morpheus/cli/option_types.rb +66 -71
  172. data/lib/morpheus/cli/policies_command.rb +0 -1
  173. data/lib/morpheus/cli/power_schedules_command.rb +3 -3
  174. data/lib/morpheus/cli/preseed_scripts_command.rb +1 -1
  175. data/lib/morpheus/cli/remote.rb +2 -2
  176. data/lib/morpheus/cli/reports_command.rb +4 -1
  177. data/lib/morpheus/cli/roles.rb +224 -64
  178. data/lib/morpheus/cli/security_group_rules.rb +1 -1
  179. data/lib/morpheus/cli/setup.rb +0 -1
  180. data/lib/morpheus/cli/subnets_command.rb +11 -2
  181. data/lib/morpheus/cli/tenants_command.rb +21 -23
  182. data/lib/morpheus/cli/user_groups_command.rb +3 -3
  183. data/lib/morpheus/cli/user_settings_command.rb +268 -57
  184. data/lib/morpheus/cli/user_sources_command.rb +3 -3
  185. data/lib/morpheus/cli/users.rb +3 -3
  186. data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
  187. data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
  188. data/lib/morpheus/cli/vdi_command.rb +359 -0
  189. data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
  190. data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
  191. data/lib/morpheus/cli/version.rb +1 -1
  192. data/lib/morpheus/cli/virtual_images.rb +1 -1
  193. data/lib/morpheus/cli/whoami.rb +0 -15
  194. data/lib/morpheus/cli/wiki_command.rb +1 -1
  195. data/lib/morpheus/ext/string.rb +41 -0
  196. data/lib/morpheus/formatters.rb +4 -0
  197. data/lib/morpheus/rest_client.rb +30 -0
  198. data/lib/morpheus/terminal.rb +15 -7
  199. metadata +27 -2
@@ -0,0 +1,246 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+ # Provides common finder methods for VDI Pool management commands
3
+ module Morpheus::Cli::VdiHelper
4
+
5
+ def self.included(klass)
6
+ klass.send :include, Morpheus::Cli::PrintHelper
7
+ end
8
+
9
+ ## VDI Pools
10
+
11
+ def vdi_pools_interface
12
+ raise "#{self.class} has not defined @vdi_pools_interface" if @vdi_pools_interface.nil?
13
+ @vdi_pools_interface
14
+ end
15
+
16
+ def vdi_pool_object_key
17
+ 'vdiPool'
18
+ end
19
+
20
+ def vdi_pool_list_key
21
+ 'vdiPools'
22
+ end
23
+
24
+ def find_vdi_pool_by_name_or_id(val)
25
+ if val.to_s =~ /\A\d{1,}\Z/
26
+ return find_vdi_pool_by_id(val)
27
+ else
28
+ return find_vdi_pool_by_name(val)
29
+ end
30
+ end
31
+
32
+ def find_vdi_pool_by_id(id)
33
+ begin
34
+ json_response = vdi_pools_interface.get(id.to_i)
35
+ return json_response[vdi_pool_object_key]
36
+ rescue RestClient::Exception => e
37
+ if e.response && e.response.code == 404
38
+ print_red_alert "VDI Pool not found by id '#{id}'"
39
+ else
40
+ raise e
41
+ end
42
+ end
43
+ end
44
+
45
+ def find_vdi_pool_by_name(name)
46
+ json_response = vdi_pools_interface.list({name: name.to_s})
47
+ vdi_pools = json_response[vdi_pool_list_key]
48
+ if vdi_pools.empty?
49
+ print_red_alert "VDI Pool not found by name '#{name}'"
50
+ return nil
51
+ elsif vdi_pools.size > 1
52
+ print_red_alert "#{vdi_pools.size} VDI Pools found by name '#{name}'"
53
+ print_error "\n"
54
+ puts_error as_pretty_table(vdi_pools, [:id, :name], {color:red})
55
+ print_red_alert "Try using ID instead"
56
+ print_error reset,"\n"
57
+ return nil
58
+ else
59
+ return vdi_pools[0]
60
+ end
61
+ end
62
+
63
+ def format_vdi_pool_status(vdi_pool, return_color=cyan)
64
+ out = ""
65
+ status_string = vdi_pool['status'].to_s.downcase
66
+ if status_string
67
+ if ['available'].include?(status_string)
68
+ out << "#{green}#{status_string.upcase}"
69
+ elsif ['unavailable'].include?(status_string)
70
+ out << "#{red}#{status_string.upcase}"
71
+ else
72
+ out << "#{return_color}#{status_string.upcase}"
73
+ end
74
+ end
75
+ out + return_color
76
+ end
77
+
78
+ ## VDI Allocations
79
+
80
+ def vdi_allocations_interface
81
+ raise "#{self.class} has not defined @vdi_allocations_interface" if @vdi_allocations_interface.nil?
82
+ @vdi_allocations_interface
83
+ end
84
+
85
+ def vdi_allocation_object_key
86
+ 'vdiAllocation'
87
+ end
88
+
89
+ def vdi_allocation_list_key
90
+ 'vdiAllocations'
91
+ end
92
+
93
+ def find_vdi_allocation_by_id(id)
94
+ begin
95
+ json_response = vdi_allocations_interface.get(id.to_i)
96
+ return json_response[vdi_allocation_object_key]
97
+ rescue RestClient::Exception => e
98
+ if e.response && e.response.code == 404
99
+ print_red_alert "VDI Allocation not found by id '#{id}'"
100
+ else
101
+ raise e
102
+ end
103
+ end
104
+ end
105
+
106
+ def format_vdi_allocation_status(vdi_allocation, return_color=cyan)
107
+ out = ""
108
+ status_string = vdi_allocation['status'].to_s.downcase
109
+ if status_string
110
+ if ['available'].include?(status_string)
111
+ out << "#{green}#{status_string.upcase}"
112
+ # elsif ['preparing'].include?(status_string)
113
+ # out << "#{yellow}#{status_string.upcase}"
114
+ # elsif ['reserved', 'shutdown'].include?(status_string)
115
+ # out << "#{yellow}#{status_string.upcase}"
116
+ elsif ['failed'].include?(status_string)
117
+ out << "#{red}#{status_string.upcase}"
118
+ else
119
+ out << "#{return_color}#{status_string.upcase}"
120
+ end
121
+ end
122
+ out + return_color
123
+ end
124
+
125
+ def get_available_vdi_apps(refresh=false)
126
+ if !@available_vdi_apps || refresh
127
+ @available_vdi_apps = @vdi_apps_interface.list({max:-1})['vdiApps'] # || []
128
+ end
129
+ return @available_vdi_apps
130
+ end
131
+
132
+ def get_vdi_app_by_name_or_code(name)
133
+ return get_available_vdi_apps().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
134
+ end
135
+
136
+ ## VDI Apps
137
+
138
+ def vdi_apps_interface
139
+ raise "#{self.class} has not defined @vdi_apps_interface" if @vdi_apps_interface.nil?
140
+ @vdi_apps_interface
141
+ end
142
+
143
+ def vdi_app_object_key
144
+ 'vdiApp'
145
+ end
146
+
147
+ def vdi_app_list_key
148
+ 'vdiApps'
149
+ end
150
+
151
+ def find_vdi_app_by_name_or_id(val)
152
+ if val.to_s =~ /\A\d{1,}\Z/
153
+ return find_vdi_app_by_id(val)
154
+ else
155
+ return find_vdi_app_by_name(val)
156
+ end
157
+ end
158
+
159
+ def find_vdi_app_by_id(id)
160
+ begin
161
+ json_response = vdi_apps_interface.get(id.to_i)
162
+ return json_response[vdi_app_object_key]
163
+ rescue RestClient::Exception => e
164
+ if e.response && e.response.code == 404
165
+ print_red_alert "VDI App not found by id '#{id}'"
166
+ else
167
+ raise e
168
+ end
169
+ end
170
+ end
171
+
172
+ def find_vdi_app_by_name(name)
173
+ json_response = vdi_apps_interface.list({name: name.to_s})
174
+ vdi_apps = json_response[vdi_app_list_key]
175
+ if vdi_apps.empty?
176
+ print_red_alert "VDI App not found by name '#{name}'"
177
+ return nil
178
+ elsif vdi_apps.size > 1
179
+ print_red_alert "#{vdi_apps.size} VDI App found by name '#{name}'"
180
+ print_error "\n"
181
+ puts_error as_pretty_table(vdi_apps, {"ID" => 'id', "NAME" => 'name'}, {color:red})
182
+ print_red_alert "Try using ID instead"
183
+ print_error reset,"\n"
184
+ return nil
185
+ else
186
+ return vdi_apps[0]
187
+ end
188
+ end
189
+
190
+
191
+ ## VDI Gateways
192
+
193
+ def vdi_gateways_interface
194
+ raise "#{self.class} has not defined @vdi_gateways_interface" if @vdi_gateways_interface.nil?
195
+ @vdi_gateways_interface
196
+ end
197
+
198
+ def vdi_gateway_object_key
199
+ 'vdiGateway'
200
+ end
201
+
202
+ def vdi_gateway_list_key
203
+ 'vdiGateways'
204
+ end
205
+
206
+ def find_vdi_gateway_by_name_or_id(val)
207
+ if val.to_s =~ /\A\d{1,}\Z/
208
+ return find_vdi_gateway_by_id(val)
209
+ else
210
+ return find_vdi_gateway_by_name(val)
211
+ end
212
+ end
213
+
214
+ def find_vdi_gateway_by_id(id)
215
+ begin
216
+ json_response = vdi_gateways_interface.get(id.to_i)
217
+ return json_response[vdi_gateway_object_key]
218
+ rescue RestClient::Exception => e
219
+ if e.response && e.response.code == 404
220
+ print_red_alert "VDI Gateway not found by id '#{id}'"
221
+ else
222
+ raise e
223
+ end
224
+ end
225
+ end
226
+
227
+ def find_vdi_gateway_by_name(name)
228
+ json_response = vdi_gateways_interface.list({name: name.to_s})
229
+ vdi_gateways = json_response[vdi_gateway_list_key]
230
+ if vdi_gateways.empty?
231
+ print_red_alert "VDI Gateway not found by name '#{name}'"
232
+ return nil
233
+ elsif vdi_gateways.size > 1
234
+ print_red_alert "#{vdi_gateways.size} VDI Gateway found by name '#{name}'"
235
+ print_error "\n"
236
+ puts_error as_pretty_table(vdi_gateways, {"ID" => 'id', "NAME" => 'name'}, {color:red})
237
+ print_red_alert "Try using ID instead"
238
+ print_error reset,"\n"
239
+ return nil
240
+ else
241
+ return vdi_gateways[0]
242
+ end
243
+ end
244
+
245
+
246
+ end
@@ -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
@@ -22,6 +24,7 @@ class Morpheus::Cli::NetworkRoutersCommand
22
24
  def connect(opts)
23
25
  @api_client = establish_remote_appliance_connection(opts)
24
26
  @network_routers_interface = @api_client.network_routers
27
+ @network_services_interface = @api_client.network_services
25
28
  @clouds_interface = @api_client.clouds
26
29
  @options_interface = @api_client.options
27
30
  @accounts_interface = @api_client.accounts
@@ -106,7 +109,7 @@ class Morpheus::Cli::NetworkRoutersCommand
106
109
  options = {}
107
110
  optparse = Morpheus::Cli::OptionParser.new do |opts|
108
111
  opts.banner = subcommand_usage("[router]")
109
- opts.on('--details', "Display details: firewall, DHCP, and routing." ) do
112
+ opts.on('--details', "Display details: firewall, DHCP, routing, and NATs." ) do
110
113
  options[:details] = true
111
114
  end
112
115
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
@@ -191,7 +194,7 @@ class Morpheus::Cli::NetworkRoutersCommand
191
194
  if router['type']['hasFirewall']
192
195
  print_h2 "Firewall"
193
196
  print cyan
194
- print_firewall(router, options[:details])
197
+ print_firewall(router, options)
195
198
  end
196
199
  if router['type']['hasDhcp']
197
200
  print_h2 "DHCP"
@@ -203,6 +206,11 @@ class Morpheus::Cli::NetworkRoutersCommand
203
206
  print cyan
204
207
  print_routes(router)
205
208
  end
209
+ if router['type']['hasNat'] && options[:details]
210
+ print_h2 "NATs"
211
+ print cyan
212
+ print_nats(router)
213
+ end
206
214
  if router['permissions'] && options[:details]
207
215
  print_h2 "Tenant Permissions"
208
216
  print cyan
@@ -249,6 +257,9 @@ class Morpheus::Cli::NetworkRoutersCommand
249
257
  opts.on('--enabled [on|off]', String, "Can be used to enable / disable the network router. Default is on") do |val|
250
258
  options[:enabled] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
251
259
  end
260
+ opts.on('--hostname VALUE', String, "Hostname for this network pool IP") do |val|
261
+ options[:options]['hostname'] = val
262
+ end
252
263
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
253
264
  opts.footer = "Create a network router."
254
265
  end
@@ -275,7 +286,7 @@ class Morpheus::Cli::NetworkRoutersCommand
275
286
  group_options = available_groups
276
287
 
277
288
  if options[:group]
278
- group = avail_groups.find {|it| it['name'] == options[:group] || "#{it['value']}" == "#{options[:group]}".downcase}
289
+ group = available_groups.find {|it| it['name'] == options[:group] || "#{it['value']}" == "#{options[:group]}".downcase}
279
290
 
280
291
  if group.nil?
281
292
  print_red_alert "Group #{options[:group]} not found"
@@ -292,10 +303,10 @@ class Morpheus::Cli::NetworkRoutersCommand
292
303
  params = {'router' => {'site' => router['site']}, 'routerType' => {'id' => router_type['id']}}
293
304
 
294
305
  if router_type['hasNetworkServer']
295
- if options[:server]
296
- server = find_network_server(options[:server])
306
+ if options[:network_server]
307
+ server = find_network_server(options[:network_server])
297
308
  if server.nil?
298
- print_red_alert "Network server #{options[:server]} not found"
309
+ print_red_alert "Network server #{options[:network_server]} not found"
299
310
  exit 1
300
311
  end
301
312
  else
@@ -322,7 +333,7 @@ class Morpheus::Cli::NetworkRoutersCommand
322
333
  # prompt for enabled
323
334
  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
335
 
325
- option_types = router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
336
+ option_types = router_type['optionTypes'].reject {|it| ['enabled'].include?(it['fieldName']) || it['showOnCreate'] === false}.sort {|it| it['displayOrder']}
326
337
 
327
338
  # prompt options
328
339
  option_opts = options[:options].deep_merge!({'config' => options[:options].clone})
@@ -356,9 +367,15 @@ class Morpheus::Cli::NetworkRoutersCommand
356
367
  params = {}
357
368
  optparse = Morpheus::Cli::OptionParser.new do|opts|
358
369
  opts.banner = subcommand_usage("[router]")
359
- 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|
360
374
  params['description'] = val
361
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
362
379
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
363
380
  opts.footer = "Update a network router."
364
381
  end
@@ -384,7 +401,7 @@ class Morpheus::Cli::NetworkRoutersCommand
384
401
  end
385
402
 
386
403
  if options[:options]
387
- 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)})
388
405
  end
389
406
  payload = {'networkRouter' => params}
390
407
  end
@@ -464,6 +481,9 @@ class Morpheus::Cli::NetworkRoutersCommand
464
481
  options = {}
465
482
  optparse = Morpheus::Cli::OptionParser.new do |opts|
466
483
  opts.banner = subcommand_usage("[router]")
484
+ opts.on('--details', "Display details." ) do
485
+ options[:details] = true
486
+ end
467
487
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
468
488
  opts.footer = "Display network router firewall details." + "\n" +
469
489
  "[router] is required. This is the name or id of a network router."
@@ -476,21 +496,18 @@ class Morpheus::Cli::NetworkRoutersCommand
476
496
  puts optparse
477
497
  return 1
478
498
  end
479
- _firewall(args[0], options)
480
- end
481
499
 
482
- def _firewall(router_id, options)
483
500
  begin
484
501
  @network_routers_interface.setopts(options)
485
502
  if options[:dry_run]
486
503
  if args[0].to_s =~ /\A\d{1,}\Z/
487
- 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)
488
505
  else
489
- print_dry_run @network_routers_interface.dry.list({name:router_id})
506
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
490
507
  end
491
508
  return
492
509
  end
493
- router = find_router(router_id)
510
+ router = find_router(args[0])
494
511
  if router.nil?
495
512
  return 1
496
513
  end
@@ -508,34 +525,930 @@ class Morpheus::Cli::NetworkRoutersCommand
508
525
  return 0
509
526
  end
510
527
 
511
- if !options[:rules_only]
512
- print_h1 "Network Router Firewall Details for: #{router['name']}"
513
- end
514
-
528
+ print_h1 "Network Router Firewall Details For: #{router['name']}"
515
529
  print cyan
516
530
 
517
531
  if router['type']['hasFirewall']
518
- print_firewall(router, true, options[:rules_only])
532
+ print_firewall(router, options)
533
+ else
534
+ print_red_alert "Firewall not supported for #{router['type']['name']}"
535
+ end
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)
519
1411
  else
520
- print_red_alert "Firewall not supported for #{router['type']['name']}"
1412
+ print_red_alert "Routes not supported for #{router['type']['name']}"
521
1413
  end
522
- println reset
1414
+ print reset
523
1415
  rescue RestClient::Exception => e
524
1416
  print_rest_exception(e, options)
525
1417
  return 1
526
1418
  end
527
1419
  end
528
1420
 
529
- def add_firewall_rule(args)
1421
+ def add_route(args)
530
1422
  options = {:options=>{}}
531
1423
  params = {}
532
1424
  optparse = Morpheus::Cli::OptionParser.new do|opts|
533
1425
  opts.banner = subcommand_usage("[router] [name]")
534
- opts.on('-n', '--name VALUE', String, "Name for this firewall rule") do |val|
1426
+ opts.on('-n', '--name VALUE', String, "Name for this route") do |val|
535
1427
  params['name'] = val
536
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
1449
+ end
537
1450
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
538
- opts.footer = "Create a network router firewall rule."
1451
+ opts.footer = "Create a network router route."
539
1452
  end
540
1453
  optparse.parse!(args)
541
1454
  connect(options)
@@ -554,55 +1467,61 @@ class Morpheus::Cli::NetworkRoutersCommand
554
1467
  return 1
555
1468
  end
556
1469
 
557
- if !router['type']['hasFirewall']
558
- 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']}"
559
1472
  return 1
560
1473
  end
561
1474
 
562
1475
  if options[:payload]
563
1476
  payload = options[:payload]
1477
+ payload = {'networkRoute' => payload['route']} if payload['route']
564
1478
  else
565
- 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']
566
1481
 
567
- 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]
568
1484
 
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)}
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}
575
1494
  end
576
1495
 
577
1496
  @network_routers_interface.setopts(options)
578
1497
  if options[:dry_run]
579
- 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)
580
1499
  return
581
1500
  end
582
1501
 
583
- json_response = @network_routers_interface.create_firewall_rule(router['id'], payload)
1502
+ json_response = @network_routers_interface.create_route(router['id'], payload)
584
1503
 
585
1504
  if options[:json]
586
1505
  print JSON.pretty_generate(json_response), "\n"
587
1506
  return
588
1507
  end
589
- print_green_success "\nAdded Network Router Firewall Rule #{payload['rule']['name']}\n"
590
- _firewall(router['id'], options.merge({:rules_only => true}))
1508
+ print_green_success "\nAdded Network Router Route #{payload['networkRoute']['name']}"
1509
+ _routes(router['id'], options)
591
1510
  rescue RestClient::Exception => e
592
1511
  print_rest_exception(e, options)
593
1512
  exit 1
594
1513
  end
595
1514
  end
596
1515
 
597
- def remove_firewall_rule(args)
1516
+ def remove_route(args)
598
1517
  options = {}
599
1518
  query_params = {}
600
1519
  optparse = Morpheus::Cli::OptionParser.new do |opts|
601
1520
  opts.banner = subcommand_usage("[router] [rule]")
602
1521
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
603
- opts.footer = "Delete a network router firewall rule.\n" +
1522
+ opts.footer = "Delete a network router route.\n" +
604
1523
  "[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."
1524
+ "[route] is required. This is the name or id of an existing network router route."
606
1525
  end
607
1526
  optparse.parse!(args)
608
1527
  if args.count != 2
@@ -614,28 +1533,28 @@ class Morpheus::Cli::NetworkRoutersCommand
614
1533
  router = find_router(args[0])
615
1534
  return if !router
616
1535
 
617
- 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
618
1537
 
619
- if !rule
620
- 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']}"
621
1540
  exit 1
622
1541
  end
623
1542
 
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)
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)
625
1544
  return 9, "aborted command"
626
1545
  end
627
1546
  @network_routers_interface.setopts(options)
628
1547
  if options[:dry_run]
629
- 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'])
630
1549
  return
631
1550
  end
632
- json_response = @network_routers_interface.destroy_firewall_rule(router['id'], rule['id'])
1551
+ json_response = @network_routers_interface.destroy_route(router['id'], route['id'])
633
1552
  if options[:json]
634
1553
  print JSON.pretty_generate(json_response)
635
1554
  print "\n"
636
1555
  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}))
1556
+ print_green_success "\nRoute #{route['name']} for router #{router['name']} is being removed..."
1557
+ _routes(router['id'], options)
639
1558
  end
640
1559
  rescue RestClient::Exception => e
641
1560
  print_rest_exception(e, options)
@@ -643,13 +1562,13 @@ class Morpheus::Cli::NetworkRoutersCommand
643
1562
  end
644
1563
  end
645
1564
 
646
- def dhcp(args)
1565
+ def nats(args)
647
1566
  options = {}
648
1567
  optparse = Morpheus::Cli::OptionParser.new do |opts|
649
1568
  opts.banner = subcommand_usage("[router]")
650
1569
  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."
1570
+ opts.footer = "List network router NATs." + "\n" +
1571
+ "[router] is required. This is the name or id of a network router."
653
1572
  end
654
1573
 
655
1574
  optparse.parse!(args)
@@ -659,141 +1578,141 @@ class Morpheus::Cli::NetworkRoutersCommand
659
1578
  puts optparse
660
1579
  return 1
661
1580
  end
1581
+ _nats(args[0], options)
1582
+ end
662
1583
 
1584
+ def _nats(router_id, options)
663
1585
  begin
664
1586
  @network_routers_interface.setopts(options)
665
1587
  if options[:dry_run]
666
1588
  if args[0].to_s =~ /\A\d{1,}\Z/
667
- 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)
668
1590
  else
669
- print_dry_run @network_routers_interface.dry.list({name:args[0]})
1591
+ print_dry_run @network_routers_interface.dry.list({name:router_id})
670
1592
  end
671
1593
  return
672
1594
  end
673
- router = find_router(args[0])
1595
+ router = find_router(router_id)
674
1596
  if router.nil?
675
1597
  return 1
676
1598
  end
677
1599
 
678
- json_response = {'networkRouter' => router}
1600
+ json_response = {'networkRouterNATs' => router['nats']}
679
1601
 
680
1602
  if options[:json]
681
- puts as_json(json_response, options, "networkRouter")
1603
+ puts as_json(json_response, options, "networkRouterNATs")
682
1604
  return 0
683
1605
  elsif options[:yaml]
684
- puts as_yaml(json_response, options, "networkRouter")
1606
+ puts as_yaml(json_response, options, "networkRouterNATs")
685
1607
  return 0
686
1608
  elsif options[:csv]
687
- puts records_as_csv([json_response['networkRouter']], options)
1609
+ puts records_as_csv(json_response['networkRouterNATs'], options)
688
1610
  return 0
689
1611
  end
690
1612
 
691
- print_h1 "Network Router DHCP Details for: #{router['name']}"
1613
+ print_h1 "Network Router NATs For: #{router['name']}"
692
1614
  print cyan
693
1615
 
694
- if router['type']['hasDhcp']
695
- print_dhcp(router, true)
1616
+ if router['type']['hasNat']
1617
+ print_nats(router)
696
1618
  else
697
- print_red_alert "DHCP not supported for #{router['type']['name']}"
1619
+ print_red_alert "NATs not supported for #{router['type']['name']}"
698
1620
  end
699
- println reset
1621
+ print reset
700
1622
  rescue RestClient::Exception => e
701
1623
  print_rest_exception(e, options)
702
1624
  return 1
703
1625
  end
704
1626
  end
705
1627
 
706
- def routes(args)
1628
+ def nat(args)
707
1629
  options = {}
708
1630
  optparse = Morpheus::Cli::OptionParser.new do |opts|
709
- opts.banner = subcommand_usage("[router]")
1631
+ opts.banner = subcommand_usage("[router] [rule]")
710
1632
  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."
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"
713
1636
  end
714
1637
 
715
1638
  optparse.parse!(args)
716
1639
  connect(options)
717
1640
 
718
- if args.count < 1
1641
+ if args.count < 2
719
1642
  puts optparse
720
1643
  return 1
721
1644
  end
722
- _routes(args[0], options)
723
- end
724
1645
 
725
- def _routes(router_id, options)
726
1646
  begin
727
1647
  @network_routers_interface.setopts(options)
728
1648
  if options[:dry_run]
729
1649
  if args[0].to_s =~ /\A\d{1,}\Z/
730
- 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)
731
1651
  else
732
- print_dry_run @network_routers_interface.dry.list({name:router_id})
1652
+ print_dry_run @network_routers_interface.dry.list({name:args[0]})
733
1653
  end
734
1654
  return
735
1655
  end
736
- router = find_router(router_id)
1656
+ router = find_router(args[0])
737
1657
  if router.nil?
738
1658
  return 1
739
1659
  end
740
1660
 
741
- 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]}
742
1663
 
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
1664
+ if nat
1665
+ json_response = {'networkRouterNAT' => nat}
753
1666
 
754
- print_h1 "Network Router Routes for: #{router['name']}"
755
- 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
756
1677
 
757
- if router['type']['hasRouting']
758
- 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
759
1696
  else
760
- print_red_alert "Routes not supported for #{router['type']['name']}"
1697
+ print_red_alert "NATs not supported for #{router['type']['name']}"
761
1698
  end
762
- print reset
1699
+ println reset
763
1700
  rescue RestClient::Exception => e
764
1701
  print_rest_exception(e, options)
765
1702
  return 1
766
1703
  end
767
1704
  end
768
1705
 
769
- def add_route(args)
1706
+ def add_nat(args)
770
1707
  options = {:options=>{}}
771
1708
  params = {}
772
1709
  optparse = Morpheus::Cli::OptionParser.new do|opts|
773
1710
  opts.banner = subcommand_usage("[router] [name]")
774
- 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|
775
1712
  params['name'] = val
776
1713
  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
1714
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
796
- opts.footer = "Create a network router route."
1715
+ opts.footer = "Create a network router NAT."
797
1716
  end
798
1717
  optparse.parse!(args)
799
1718
  connect(options)
@@ -812,8 +1731,8 @@ class Morpheus::Cli::NetworkRoutersCommand
812
1731
  return 1
813
1732
  end
814
1733
 
815
- if !router['type']['hasRouting']
816
- 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']}"
817
1736
  return 1
818
1737
  end
819
1738
 
@@ -821,50 +1740,108 @@ class Morpheus::Cli::NetworkRoutersCommand
821
1740
  payload = options[:payload]
822
1741
  else
823
1742
  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
1743
 
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]
1744
+ option_types = router['type']['natOptionTypes'].reject {|it| ['name'].include?(it['fieldName'])}.sort {|it| it['displayOrder']}
828
1745
 
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]
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
831
1750
 
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']
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?
835
1810
 
836
- payload = {'route' => params}
1811
+ if payload['networkRouterNAT'].empty?
1812
+ print_green_success "Nothing to update"
1813
+ exit 1
837
1814
  end
838
1815
 
839
1816
  @network_routers_interface.setopts(options)
840
1817
  if options[:dry_run]
841
- 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)
842
1819
  return
843
1820
  end
844
1821
 
845
- json_response = @network_routers_interface.create_route(router['id'], payload)
1822
+ json_response = @network_routers_interface.update_nat(router['id'], nat['id'], payload)
846
1823
 
847
1824
  if options[:json]
848
1825
  print JSON.pretty_generate(json_response), "\n"
849
1826
  return
850
1827
  end
851
- print_green_success "\nAdded Network Router Route #{payload['route']['name']}"
852
- _routes(router['id'], options)
1828
+ print_green_success "\nUpdated Network Router NAT #{nat['name']}\n"
1829
+ _nats(router['id'], options)
853
1830
  rescue RestClient::Exception => e
854
1831
  print_rest_exception(e, options)
855
1832
  exit 1
856
1833
  end
857
1834
  end
858
1835
 
859
- def remove_route(args)
1836
+ def remove_nat(args)
860
1837
  options = {}
861
1838
  query_params = {}
862
1839
  optparse = Morpheus::Cli::OptionParser.new do |opts|
863
- opts.banner = subcommand_usage("[router] [rule]")
1840
+ opts.banner = subcommand_usage("[router] [NAT]")
864
1841
  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."
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."
868
1845
  end
869
1846
  optparse.parse!(args)
870
1847
  if args.count != 2
@@ -876,28 +1853,33 @@ class Morpheus::Cli::NetworkRoutersCommand
876
1853
  router = find_router(args[0])
877
1854
  return if !router
878
1855
 
879
- 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
880
1860
 
881
- if !route
882
- 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']}"
883
1865
  exit 1
884
1866
  end
885
1867
 
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)
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)
887
1869
  return 9, "aborted command"
888
1870
  end
889
1871
  @network_routers_interface.setopts(options)
890
1872
  if options[:dry_run]
891
- 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'])
892
1874
  return
893
1875
  end
894
- json_response = @network_routers_interface.destroy_route(router['id'], route['id'])
1876
+ json_response = @network_routers_interface.destroy_nat(router['id'], nat['id'])
895
1877
  if options[:json]
896
1878
  print JSON.pretty_generate(json_response)
897
1879
  print "\n"
898
1880
  elsif !options[:quiet]
899
- print_green_success "\nRoute #{route['name']} for router #{router['name']} is being removed..."
900
- _routes(router['id'], options)
1881
+ print_green_success "\nNAT #{nat['name']} for router #{router['name']} is being removed...\n"
1882
+ _nats(router['id'], options)
901
1883
  end
902
1884
  rescue RestClient::Exception => e
903
1885
  print_rest_exception(e, options)
@@ -990,7 +1972,7 @@ class Morpheus::Cli::NetworkRoutersCommand
990
1972
  return
991
1973
  end
992
1974
 
993
- print_h1 "Network Router Type Details for: #{router_type['name']}"
1975
+ print_h1 "Network Router Type Details For: #{router_type['name']}"
994
1976
  print cyan
995
1977
 
996
1978
  description_cols = {
@@ -1007,12 +1989,14 @@ class Morpheus::Cli::NetworkRoutersCommand
1007
1989
  }
1008
1990
  print_description_list(description_cols, router_type)
1009
1991
 
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
- )
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
1016
2000
  end
1017
2001
  print reset
1018
2002
  return 0
@@ -1084,10 +2068,10 @@ class Morpheus::Cli::NetworkRoutersCommand
1084
2068
 
1085
2069
  private
1086
2070
 
1087
- def print_firewall(router, details=false, rules_only=false)
2071
+ def print_firewall(router, options = {}) #details=false, rules_only=false, rule_groups_only=false)
1088
2072
  if router['type']['hasFirewall']
1089
2073
  if router['firewall']
1090
- if details
2074
+ if options[:details]
1091
2075
  description_cols = {
1092
2076
  "Network Router" => lambda {|it| it['name'] },
1093
2077
  "Enabled" => lambda {|it| format_boolean(it['firewall']['enabled'])},
@@ -1098,28 +2082,10 @@ class Morpheus::Cli::NetworkRoutersCommand
1098
2082
  description_cols[k.gsub(/[A-Z]/, ' \0').downcase] = lambda {|it| it['firewall']['global'][k]}
1099
2083
  end
1100
2084
 
1101
- if !rules_only
1102
- print_description_list(description_cols, router)
1103
- print_h2 "Firewall Rules"
1104
- end
2085
+ print_description_list(description_cols, router)
1105
2086
 
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
2087
+ _firewall_rule_groups(router, options) if router['type']['hasFirewallGroups']
2088
+ _firewall_rules(router, options) if router['type']['hasFirewall']
1123
2089
  else
1124
2090
  print "Enabled: #{format_boolean(router['firewall']['enabled'])}".center(20)
1125
2091
  print "Version: #{router['firewall']['version']}".center(20)
@@ -1201,6 +2167,26 @@ class Morpheus::Cli::NetworkRoutersCommand
1201
2167
  end
1202
2168
  end
1203
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
+
1204
2190
  def format_router_status(router, return_color = cyan)
1205
2191
  status = router['status']
1206
2192
  color = white
@@ -1219,7 +2205,9 @@ class Morpheus::Cli::NetworkRoutersCommand
1219
2205
  if val.to_s =~ /\A\d{1,}\Z/
1220
2206
  return find_router_by_id(val)
1221
2207
  else
1222
- return find_router_by_name(val)
2208
+ if router = find_router_by_name(val)
2209
+ return find_router_by_id(router['id'])
2210
+ end
1223
2211
  end
1224
2212
  end
1225
2213
 
@@ -1278,4 +2266,27 @@ class Morpheus::Cli::NetworkRoutersCommand
1278
2266
  def available_groups()
1279
2267
  @network_routers_interface.groups
1280
2268
  end
2269
+
2270
+ def find_network_server(val)
2271
+ services = @network_services_interface.list()['networkServices']
2272
+ (val.to_s =~ /\A\d{1,}\Z/) ? services.find {|it| it['id'].to_i == val.to_i} : services.find {|it| it['name'] == val}
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
1281
2292
  end