vcloud-edge_gateway 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +16 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +20 -0
- data/README.md +160 -0
- data/Rakefile +23 -0
- data/bin/vcloud-edge +12 -0
- data/jenkins.sh +11 -0
- data/lib/vcloud/config_loader.rb +27 -0
- data/lib/vcloud/config_validator.rb +207 -0
- data/lib/vcloud/edge_gateway/configuration_differ.rb +17 -0
- data/lib/vcloud/edge_gateway/configuration_generator/firewall_service.rb +63 -0
- data/lib/vcloud/edge_gateway/configuration_generator/id_ranges.rb +10 -0
- data/lib/vcloud/edge_gateway/configuration_generator/load_balancer_service.rb +243 -0
- data/lib/vcloud/edge_gateway/configuration_generator/nat_service.rb +54 -0
- data/lib/vcloud/edge_gateway/edge_gateway_configuration.rb +41 -0
- data/lib/vcloud/edge_gateway/version.rb +6 -0
- data/lib/vcloud/edge_gateway.rb +32 -0
- data/lib/vcloud/edge_gateway_services.rb +26 -0
- data/lib/vcloud/schema/edge_gateway.rb +15 -0
- data/lib/vcloud/schema/firewall_service.rb +39 -0
- data/lib/vcloud/schema/load_balancer_service.rb +129 -0
- data/lib/vcloud/schema/nat_service.rb +35 -0
- data/scripts/generate_fog_conf_file.sh +6 -0
- data/spec/erb_helper.rb +11 -0
- data/spec/integration/edge_gateway/data/firewall_config.yaml.erb +17 -0
- data/spec/integration/edge_gateway/data/firewall_config_updated_rule.yaml.erb +17 -0
- data/spec/integration/edge_gateway/data/firewall_rule_order_test.yaml.erb +24 -0
- data/spec/integration/edge_gateway/data/hairpin_nat_config.yaml.erb +13 -0
- data/spec/integration/edge_gateway/data/incorrect_firewall_config.yaml +14 -0
- data/spec/integration/edge_gateway/data/nat_and_firewall_config.yaml.erb +32 -0
- data/spec/integration/edge_gateway/data/nat_config.yaml.erb +17 -0
- data/spec/integration/edge_gateway/edge_gateway_services_spec.rb +132 -0
- data/spec/integration/edge_gateway/firewall_service_spec.rb +201 -0
- data/spec/integration/edge_gateway/nat_service_spec.rb +208 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/vcloud/config_loader_spec.rb +112 -0
- data/spec/vcloud/config_validator_spec.rb +570 -0
- data/spec/vcloud/data/basic_preamble_test.erb +8 -0
- data/spec/vcloud/data/basic_preamble_test.erb.OUT +8 -0
- data/spec/vcloud/data/working.json +21 -0
- data/spec/vcloud/data/working.yaml +22 -0
- data/spec/vcloud/data/working_with_defaults.yaml +25 -0
- data/spec/vcloud/edge_gateway/configuration_differ_spec.rb +131 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_http-input.yaml +41 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_http-output.yaml +93 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_https-input.yaml +39 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_https-output.yaml +92 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_mixed_complex-input.yaml +65 -0
- data/spec/vcloud/edge_gateway/configuration_generator/data/load_balancer_mixed_complex-output.yaml +94 -0
- data/spec/vcloud/edge_gateway/configuration_generator/firewall_service_spec.rb +378 -0
- data/spec/vcloud/edge_gateway/configuration_generator/load_balancer_service_spec.rb +233 -0
- data/spec/vcloud/edge_gateway/configuration_generator/nat_service_spec.rb +360 -0
- data/spec/vcloud/edge_gateway/edge_gateway_configuration_spec.rb +182 -0
- data/spec/vcloud/edge_gateway/firewall_schema_validation_spec.rb +45 -0
- data/spec/vcloud/edge_gateway/load_balancer_schema_validation_spec.rb +153 -0
- data/spec/vcloud/edge_gateway/nat_schema_validation_spec.rb +93 -0
- data/vcloud-edge_gateway.gemspec +32 -0
- metadata +252 -0
@@ -0,0 +1,243 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module EdgeGateway
|
3
|
+
module ConfigurationGenerator
|
4
|
+
class LoadBalancerService
|
5
|
+
|
6
|
+
def initialize edge_gateway
|
7
|
+
@edge_gateway = Vcloud::Core::EdgeGateway.get_by_name(edge_gateway)
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate_fog_config(load_balancer_input_config)
|
11
|
+
return nil if load_balancer_input_config.nil?
|
12
|
+
vcloud_load_balancer_section = {}
|
13
|
+
vcloud_load_balancer_section[:IsEnabled] =
|
14
|
+
load_balancer_input_config.key?(:enabled) ?
|
15
|
+
load_balancer_input_config[:enabled].to_s : 'true'
|
16
|
+
vcloud_pools = []
|
17
|
+
vcloud_virtual_servers = []
|
18
|
+
if pools = load_balancer_input_config[:pools]
|
19
|
+
pools.each do |pool_input_entry|
|
20
|
+
vcloud_pools << generate_pool_entry(pool_input_entry)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
if virtual_servers = load_balancer_input_config[:virtual_servers]
|
24
|
+
virtual_servers.each do |virtual_server_input_entry|
|
25
|
+
vcloud_virtual_servers << generate_virtual_server_entry(virtual_server_input_entry)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
vcloud_load_balancer_section[:Pool] = vcloud_pools
|
29
|
+
vcloud_load_balancer_section[:VirtualServer] = vcloud_virtual_servers
|
30
|
+
vcloud_load_balancer_section
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def generate_virtual_server_entry(input_virtual_server)
|
36
|
+
vcloud_virtual_server = {}
|
37
|
+
vcloud_virtual_server[:IsEnabled] =
|
38
|
+
input_virtual_server.key(:enabled) ? input_virtual_server[:enabled] : 'true'
|
39
|
+
vcloud_virtual_server[:Name] = input_virtual_server[:name]
|
40
|
+
vcloud_virtual_server[:Description] =
|
41
|
+
input_virtual_server[:description] || ''
|
42
|
+
vcloud_virtual_server[:Interface] =
|
43
|
+
generate_virtual_server_interface_section(input_virtual_server[:network])
|
44
|
+
vcloud_virtual_server[:IpAddress] = input_virtual_server[:ip_address]
|
45
|
+
vcloud_virtual_server[:ServiceProfile] =
|
46
|
+
generate_virtual_server_service_profile_section(input_virtual_server[:service_profiles])
|
47
|
+
vcloud_virtual_server[:Logging] =
|
48
|
+
input_virtual_server.key(:logging) ? input_virtual_server[:logging] : 'false'
|
49
|
+
vcloud_virtual_server[:Pool] = input_virtual_server[:pool]
|
50
|
+
vcloud_virtual_server
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_virtual_server_interface_section(network_id)
|
54
|
+
vcloud_virtual_server_interface = {}
|
55
|
+
vcloud_virtual_server_interface[:type] = 'application/vnd.vmware.vcloud.orgVdcNetwork+xml'
|
56
|
+
vcloud_virtual_server_interface[:name] = look_up_network_name(network_id)
|
57
|
+
vcloud_virtual_server_interface[:href] = look_up_network_href(network_id)
|
58
|
+
vcloud_virtual_server_interface
|
59
|
+
end
|
60
|
+
|
61
|
+
def look_up_network_name(network_id)
|
62
|
+
gateway_interface = @edge_gateway.vcloud_gateway_interface_by_id(network_id)
|
63
|
+
raise "Could not find network #{network_id}" unless gateway_interface
|
64
|
+
gateway_interface[:Network][:name]
|
65
|
+
end
|
66
|
+
|
67
|
+
def look_up_network_href(network_id)
|
68
|
+
gateway_interface = @edge_gateway.vcloud_gateway_interface_by_id(network_id)
|
69
|
+
raise "Could not find network #{network_id}" unless gateway_interface
|
70
|
+
gateway_interface[:Network][:href]
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_virtual_server_service_profile_section(input_service_profile)
|
74
|
+
input_service_profile = {} if input_service_profile.nil?
|
75
|
+
vcloud_service_profiles = []
|
76
|
+
protocols = [ :http, :https, :tcp ]
|
77
|
+
protocols.each do |protocol|
|
78
|
+
vcloud_service_profiles <<
|
79
|
+
generate_virtual_server_service_profile_protocol_section(
|
80
|
+
protocol,
|
81
|
+
input_service_profile[protocol]
|
82
|
+
)
|
83
|
+
end
|
84
|
+
vcloud_service_profiles
|
85
|
+
end
|
86
|
+
|
87
|
+
def generate_virtual_server_service_profile_protocol_section(protocol, input_protocol_section)
|
88
|
+
vcloud_protocol_section = {
|
89
|
+
IsEnabled: 'false',
|
90
|
+
Protocol: protocol.to_s.upcase,
|
91
|
+
Port: default_port(protocol),
|
92
|
+
Persistence: generate_virtual_server_persistence_section(protocol, nil)
|
93
|
+
}
|
94
|
+
if input_protocol_section
|
95
|
+
vcloud_protocol_section[:IsEnabled] =
|
96
|
+
input_protocol_section.key?(:enabled) ?
|
97
|
+
input_protocol_section[:enabled].to_s : 'true'
|
98
|
+
vcloud_protocol_section[:Port] =
|
99
|
+
input_protocol_section.key?(:port) ?
|
100
|
+
input_protocol_section[:port].to_s : default_port(protocol)
|
101
|
+
vcloud_protocol_section[:Persistence] =
|
102
|
+
generate_virtual_server_persistence_section(
|
103
|
+
protocol,
|
104
|
+
input_protocol_section[:persistence]
|
105
|
+
)
|
106
|
+
end
|
107
|
+
vcloud_protocol_section
|
108
|
+
end
|
109
|
+
|
110
|
+
def default_port(protocol)
|
111
|
+
default_port_for = { http: '80', https: '443', tcp: '' }
|
112
|
+
default_port_for[protocol]
|
113
|
+
end
|
114
|
+
|
115
|
+
def generate_virtual_server_persistence_section(protocol, input_persistence_section)
|
116
|
+
input_persistence_section = {} if input_persistence_section.nil?
|
117
|
+
vcloud_persistence_section = { Method: '' }
|
118
|
+
if input_persistence_section.key?(:method)
|
119
|
+
if input_persistence_section.key?(:method)
|
120
|
+
vcloud_persistence_section[:Method] = input_persistence_section[:method]
|
121
|
+
end
|
122
|
+
if input_persistence_section[:method] == 'COOKIE'
|
123
|
+
vcloud_persistence_section[:CookieName] = input_persistence_section[:cookie_name]
|
124
|
+
vcloud_persistence_section[:CookieMode] = input_persistence_section[:cookie_mode]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
vcloud_persistence_section
|
128
|
+
end
|
129
|
+
|
130
|
+
def generate_pool_entry(input_pool_entry)
|
131
|
+
service_port_modes = [ :http, :https, :tcp ]
|
132
|
+
vcloud_pool_entry = {}
|
133
|
+
vcloud_pool_entry[:Name] = input_pool_entry[:name]
|
134
|
+
if input_pool_entry.key?(:description)
|
135
|
+
vcloud_pool_entry[:Description] = input_pool_entry[:description]
|
136
|
+
end
|
137
|
+
vcloud_pool_entry[:ServicePort] = service_port_modes.map do |mode|
|
138
|
+
generate_pool_service_port(
|
139
|
+
mode,
|
140
|
+
input_pool_entry.key?(:service) ? input_pool_entry[:service][mode] : nil
|
141
|
+
)
|
142
|
+
end
|
143
|
+
if input_pool_entry.key?(:members)
|
144
|
+
vcloud_pool_entry[:Member] = []
|
145
|
+
input_pool_entry[:members].each do |member|
|
146
|
+
vcloud_pool_entry[:Member] << generate_pool_member_entry(member)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
vcloud_pool_entry
|
150
|
+
end
|
151
|
+
|
152
|
+
def generate_pool_member_entry(input_pool_member)
|
153
|
+
{
|
154
|
+
IpAddress: input_pool_member[:ip_address],
|
155
|
+
Weight: input_pool_member.key?(:weight) ? input_pool_member[:weight].to_s : '1',
|
156
|
+
ServicePort: [
|
157
|
+
{ Protocol: 'HTTP', Port: '', HealthCheckPort: '' },
|
158
|
+
{ Protocol: 'HTTPS', Port: '', HealthCheckPort: '' },
|
159
|
+
{ Protocol: 'TCP', Port: '', HealthCheckPort: '' },
|
160
|
+
]
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
def generate_pool_service_port(mode, input_pool_service_port)
|
165
|
+
|
166
|
+
vcloud_pool_service_port = {
|
167
|
+
IsEnabled: 'false',
|
168
|
+
Protocol: mode.to_s.upcase,
|
169
|
+
Algorithm: 'ROUND_ROBIN',
|
170
|
+
Port: default_port(mode),
|
171
|
+
HealthCheckPort: '',
|
172
|
+
HealthCheck: generate_pool_healthcheck(mode)
|
173
|
+
}
|
174
|
+
|
175
|
+
if input_pool_service_port
|
176
|
+
vcloud_pool_service_port[:IsEnabled] =
|
177
|
+
input_pool_service_port.key?(:enabled) ?
|
178
|
+
input_pool_service_port[:enabled].to_s : 'true'
|
179
|
+
if input_pool_service_port.key?(:algorithm)
|
180
|
+
vcloud_pool_service_port[:Algorithm] = input_pool_service_port[:algorithm]
|
181
|
+
end
|
182
|
+
vcloud_pool_service_port[:Port] =
|
183
|
+
input_pool_service_port.key?(:port) ?
|
184
|
+
input_pool_service_port[:port].to_s : default_port(mode)
|
185
|
+
if health_check = input_pool_service_port[:health_check]
|
186
|
+
vcloud_pool_service_port[:HealthCheckPort] =
|
187
|
+
health_check.key?(:port) ? health_check[:port].to_s : ''
|
188
|
+
vcloud_pool_service_port[:HealthCheck] =
|
189
|
+
generate_pool_healthcheck(mode, input_pool_service_port[:health_check])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
vcloud_pool_service_port
|
193
|
+
end
|
194
|
+
|
195
|
+
def generate_pool_healthcheck(protocol, input_pool_healthcheck_entry = nil)
|
196
|
+
default_mode = ( protocol == :https ) ? 'SSL' : protocol.to_s.upcase
|
197
|
+
vcloud_pool_healthcheck_entry = {
|
198
|
+
Mode: default_mode,
|
199
|
+
}
|
200
|
+
if protocol == :http
|
201
|
+
vcloud_pool_healthcheck_entry[:Uri] = ''
|
202
|
+
elsif ( protocol == :https ) &&
|
203
|
+
input_pool_healthcheck_entry &&
|
204
|
+
( input_pool_healthcheck_entry[:protocol] == 'TCP' )
|
205
|
+
vcloud_pool_healthcheck_entry[:Uri] = ''
|
206
|
+
end
|
207
|
+
vcloud_pool_healthcheck_entry[:HealthThreshold] = '2'
|
208
|
+
vcloud_pool_healthcheck_entry[:UnhealthThreshold] = '3'
|
209
|
+
vcloud_pool_healthcheck_entry[:Interval] = '5'
|
210
|
+
vcloud_pool_healthcheck_entry[:Timeout] = '15'
|
211
|
+
|
212
|
+
if input_pool_healthcheck_entry
|
213
|
+
if input_pool_healthcheck_entry.key?(:protocol)
|
214
|
+
vcloud_pool_healthcheck_entry[:Mode] = input_pool_healthcheck_entry[:protocol]
|
215
|
+
end
|
216
|
+
if input_pool_healthcheck_entry.key?(:uri) and protocol == :http
|
217
|
+
vcloud_pool_healthcheck_entry[:Uri] = input_pool_healthcheck_entry[:uri]
|
218
|
+
end
|
219
|
+
if input_pool_healthcheck_entry.key?(:health_threshold)
|
220
|
+
vcloud_pool_healthcheck_entry[:HealthThreshold] =
|
221
|
+
input_pool_healthcheck_entry[:health_threshold]
|
222
|
+
end
|
223
|
+
if input_pool_healthcheck_entry.key?(:unhealth_threshold)
|
224
|
+
vcloud_pool_healthcheck_entry[:UnhealthThreshold] =
|
225
|
+
input_pool_healthcheck_entry[:unhealth_threshold]
|
226
|
+
end
|
227
|
+
if input_pool_healthcheck_entry.key?(:interval)
|
228
|
+
vcloud_pool_healthcheck_entry[:Interval] =
|
229
|
+
input_pool_healthcheck_entry[:interval]
|
230
|
+
end
|
231
|
+
if input_pool_healthcheck_entry.key?(:timeout)
|
232
|
+
vcloud_pool_healthcheck_entry[:Timeout] =
|
233
|
+
input_pool_healthcheck_entry[:timeout]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
vcloud_pool_healthcheck_entry
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module EdgeGateway
|
3
|
+
module ConfigurationGenerator
|
4
|
+
|
5
|
+
class NatService
|
6
|
+
def initialize edge_gateway, input_config
|
7
|
+
@edge_gateway = Vcloud::Core::EdgeGateway.get_by_name(edge_gateway)
|
8
|
+
@input_config = input_config
|
9
|
+
@interfaces_by_id = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_fog_config
|
13
|
+
if @input_config
|
14
|
+
nat_service = {}
|
15
|
+
nat_service[:IsEnabled] = @input_config.key?(:enabled) ? @input_config[:enabled].to_s : 'true'
|
16
|
+
nat_service[:NatRule] = populate_nat_rules
|
17
|
+
nat_service
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def populate_nat_rules
|
22
|
+
rules = @input_config[:nat_rules]
|
23
|
+
i = ID_RANGES::NAT_SERVICE[:min]
|
24
|
+
rules.collect do |rule|
|
25
|
+
new_rule = {}
|
26
|
+
new_rule[:Id] = rule.key?(:id) ? rule[:id] : i.to_s
|
27
|
+
new_rule[:IsEnabled] = rule.key?(:enabled) ? rule[:enabled].to_s : 'true'
|
28
|
+
new_rule[:RuleType] = rule[:rule_type]
|
29
|
+
gateway_nat_rule = populate_gateway_nat_rule(rule)
|
30
|
+
new_rule[:GatewayNatRule] = gateway_nat_rule
|
31
|
+
i += 1
|
32
|
+
new_rule
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def populate_gateway_nat_rule(rule)
|
37
|
+
raise "Must supply a :network_id parameter" unless net_id = rule[:network_id]
|
38
|
+
@interfaces_by_id[net_id] ||= @edge_gateway.vcloud_gateway_interface_by_id(net_id)
|
39
|
+
raise "unable to find gateway network interface with id #{net_id}" unless @interfaces_by_id[net_id]
|
40
|
+
gateway_nat_rule = {:Interface => @interfaces_by_id[net_id][:Network]}
|
41
|
+
gateway_nat_rule[:OriginalIp] = rule[:original_ip]
|
42
|
+
gateway_nat_rule[:TranslatedIp] = rule[:translated_ip]
|
43
|
+
gateway_nat_rule[:OriginalPort] = rule[:original_port] if rule.key?(:original_port)
|
44
|
+
gateway_nat_rule[:TranslatedPort] = rule[:translated_port] if rule.key?(:translated_port)
|
45
|
+
if rule[:rule_type] == 'DNAT'
|
46
|
+
gateway_nat_rule[:Protocol] = rule.key?(:protocol) ? rule[:protocol] : "tcp"
|
47
|
+
end
|
48
|
+
gateway_nat_rule
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module EdgeGateway
|
3
|
+
class EdgeGatewayConfiguration
|
4
|
+
|
5
|
+
def initialize(local_config)
|
6
|
+
@local_config = local_config
|
7
|
+
@config = { }
|
8
|
+
end
|
9
|
+
|
10
|
+
def update_required?(remote_config)
|
11
|
+
update_required = false
|
12
|
+
|
13
|
+
firewall_service_config = EdgeGateway::ConfigurationGenerator::FirewallService.new.generate_fog_config(@local_config[:firewall_service])
|
14
|
+
unless firewall_service_config.nil?
|
15
|
+
differ = EdgeGateway::ConfigurationDiffer.new(firewall_service_config, remote_config[:FirewallService])
|
16
|
+
unless differ.diff.empty?
|
17
|
+
@config[:FirewallService] = firewall_service_config
|
18
|
+
update_required = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
nat_service_config = EdgeGateway::ConfigurationGenerator::NatService.new(@local_config[:gateway], @local_config[:nat_service]).generate_fog_config
|
23
|
+
|
24
|
+
unless nat_service_config.nil?
|
25
|
+
differ = EdgeGateway::ConfigurationDiffer.new(nat_service_config, remote_config[:NatService])
|
26
|
+
unless differ.diff.empty?
|
27
|
+
@config[:NatService] = nat_service_config
|
28
|
+
update_required = true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
update_required
|
33
|
+
end
|
34
|
+
|
35
|
+
def config
|
36
|
+
@config
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'vcloud/edge_gateway/version'
|
2
|
+
|
3
|
+
require 'vcloud/core'
|
4
|
+
require 'vcloud/fog'
|
5
|
+
|
6
|
+
require 'vcloud/config_loader'
|
7
|
+
require 'vcloud/config_validator'
|
8
|
+
|
9
|
+
require 'vcloud/edge_gateway_services'
|
10
|
+
|
11
|
+
require 'vcloud/schema/nat_service'
|
12
|
+
require 'vcloud/schema/firewall_service'
|
13
|
+
require 'vcloud/schema/load_balancer_service'
|
14
|
+
require 'vcloud/schema/edge_gateway'
|
15
|
+
|
16
|
+
require 'vcloud/edge_gateway/configuration_generator/id_ranges'
|
17
|
+
require 'vcloud/edge_gateway/configuration_generator/firewall_service'
|
18
|
+
require 'vcloud/edge_gateway/configuration_generator/nat_service'
|
19
|
+
require 'vcloud/edge_gateway/configuration_generator/load_balancer_service'
|
20
|
+
require 'vcloud/edge_gateway/configuration_differ'
|
21
|
+
require 'vcloud/edge_gateway/edge_gateway_configuration'
|
22
|
+
|
23
|
+
|
24
|
+
module Vcloud
|
25
|
+
module EdgeGateway
|
26
|
+
|
27
|
+
def self.logger
|
28
|
+
@logger ||=Logger.new(STDOUT)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'hashdiff'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
class EdgeGatewayServices
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@config_loader = Vcloud::ConfigLoader.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(config_file = nil)
|
11
|
+
config = @config_loader.load_config(config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES)
|
12
|
+
|
13
|
+
edge_gateway = Core::EdgeGateway.get_by_name config[:gateway]
|
14
|
+
remote_config = edge_gateway.vcloud_attributes[:Configuration][:EdgeGatewayServiceConfiguration]
|
15
|
+
|
16
|
+
proposed_config = EdgeGateway::EdgeGatewayConfiguration.new(config)
|
17
|
+
|
18
|
+
if proposed_config.update_required?(remote_config)
|
19
|
+
edge_gateway.update_configuration proposed_config.config
|
20
|
+
else
|
21
|
+
Vcloud::EdgeGateway.logger.info("EdgeGatewayServices.update: Configuration is already up to date. Skipping.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module Schema
|
3
|
+
|
4
|
+
FIREWALL_RULE = {
|
5
|
+
type: Hash,
|
6
|
+
internals: {
|
7
|
+
id: { type: 'string_or_number', required: false},
|
8
|
+
enabled: { type: 'boolean', required: false},
|
9
|
+
match_on_translate: { type: 'boolean', required: false},
|
10
|
+
description: { type: 'string', required: false, allowed_empty: true},
|
11
|
+
policy: { type: 'enum', required: false, acceptable_values: ['allow', 'drop'] },
|
12
|
+
source_ip: { type: 'ip_address_range', required: true },
|
13
|
+
destination_ip: { type: 'ip_address_range', required: true },
|
14
|
+
source_port_range: { type: 'string', required: false },
|
15
|
+
destination_port_range: { type: 'string', required: false },
|
16
|
+
enable_logging: { type: 'boolean', required: false },
|
17
|
+
protocols: { type: 'enum', required: false, acceptable_values: ['tcp', 'udp', 'icmp', 'tcp+udp', 'any']},
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
FIREWALL_SERVICE = {
|
22
|
+
type: Hash,
|
23
|
+
allowed_empty: true,
|
24
|
+
required: false,
|
25
|
+
internals: {
|
26
|
+
enabled: { type: 'boolean', required: false},
|
27
|
+
policy: { type: 'enum', required: false, acceptable_values: ['allow', 'drop'] },
|
28
|
+
log_default_action: { type: 'boolean', required: false},
|
29
|
+
firewall_rules: {
|
30
|
+
type: Array,
|
31
|
+
required: false,
|
32
|
+
allowed_empty: true,
|
33
|
+
each_element_is: FIREWALL_RULE
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module Schema
|
3
|
+
|
4
|
+
POOL_MEMBER_SERVICE_PORT_ENTRY = {
|
5
|
+
type: Hash,
|
6
|
+
required: false,
|
7
|
+
internals: {
|
8
|
+
port: { type: 'string_or_number', required: false },
|
9
|
+
health_check_port: { type: 'string_or_number', required: false },
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
LOAD_BALANCER_MEMBER_ENTRY = {
|
14
|
+
type: Hash,
|
15
|
+
internals: {
|
16
|
+
ip_address: { type: 'ip_address', required: true },
|
17
|
+
weight: { type: 'string_or_number', required: false },
|
18
|
+
service_port: {
|
19
|
+
type: 'hash',
|
20
|
+
required: false,
|
21
|
+
internals: {
|
22
|
+
http: POOL_MEMBER_SERVICE_PORT_ENTRY,
|
23
|
+
https: POOL_MEMBER_SERVICE_PORT_ENTRY,
|
24
|
+
tcp: POOL_MEMBER_SERVICE_PORT_ENTRY,
|
25
|
+
},
|
26
|
+
},
|
27
|
+
},
|
28
|
+
}
|
29
|
+
|
30
|
+
POOL_SERVICE_SECTION = {
|
31
|
+
type: Hash,
|
32
|
+
required: false,
|
33
|
+
internals: {
|
34
|
+
enabled: { type: 'boolean', required: false },
|
35
|
+
port: { type: 'string_or_number', required: false },
|
36
|
+
algorithm: { type: 'enum', required: false,
|
37
|
+
acceptable_values: [ 'ROUND_ROBIN', 'IP_HASH', 'URI', 'LEAST_CONNECTED' ]},
|
38
|
+
health_check: {
|
39
|
+
type: 'hash',
|
40
|
+
required: false,
|
41
|
+
internals: {
|
42
|
+
port: { type: 'string_or_number', required: false },
|
43
|
+
uri: { type: 'string', required: false },
|
44
|
+
protocol: { type: 'enum', required: false,
|
45
|
+
acceptable_values: [ 'HTTP', 'SSL', 'TCP' ] },
|
46
|
+
health_threshold: { type: 'string_or_number', required: false },
|
47
|
+
unhealth_threshold: { type: 'string_or_number', required: false },
|
48
|
+
interval: { type: 'string_or_number', required: false },
|
49
|
+
timeout: { type: 'string_or_number', required: false },
|
50
|
+
},
|
51
|
+
},
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
LOAD_BALANCER_POOL_ENTRY = {
|
56
|
+
type: Hash,
|
57
|
+
internals: {
|
58
|
+
name: { type: 'string', required: true },
|
59
|
+
description: { type: 'string', required: false },
|
60
|
+
service: {
|
61
|
+
type: 'hash',
|
62
|
+
required: false,
|
63
|
+
internals: {
|
64
|
+
http: POOL_SERVICE_SECTION,
|
65
|
+
https: POOL_SERVICE_SECTION,
|
66
|
+
tcp: POOL_SERVICE_SECTION,
|
67
|
+
}
|
68
|
+
},
|
69
|
+
members: {
|
70
|
+
type: Array,
|
71
|
+
required: true,
|
72
|
+
allowed_empty: false,
|
73
|
+
each_element_is: LOAD_BALANCER_MEMBER_ENTRY,
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
VIRTUAL_SERVER_SERVICE_PROFILE_ENTRY = {
|
79
|
+
type: Hash,
|
80
|
+
required: false,
|
81
|
+
internals: {
|
82
|
+
enabled: { type: 'boolean', required: false },
|
83
|
+
port: { type: 'string_or_number', required: false },
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
LOAD_BALANCER_VIRTUAL_SERVER_ENTRY = {
|
88
|
+
type: Hash,
|
89
|
+
internals: {
|
90
|
+
enabled: { type: 'boolean', required: false },
|
91
|
+
name: { type: 'string', required: true },
|
92
|
+
description: { type: 'string', required: false },
|
93
|
+
ip_address: { type: 'ip_address', required: true },
|
94
|
+
network: { type: 'string', required: true },
|
95
|
+
pool: { type: 'string', required: true },
|
96
|
+
logging: { type: 'boolean', required: false },
|
97
|
+
service_profiles: {
|
98
|
+
type: 'hash',
|
99
|
+
required: false,
|
100
|
+
internals: {
|
101
|
+
http: VIRTUAL_SERVER_SERVICE_PROFILE_ENTRY,
|
102
|
+
https: VIRTUAL_SERVER_SERVICE_PROFILE_ENTRY,
|
103
|
+
tcp: VIRTUAL_SERVER_SERVICE_PROFILE_ENTRY,
|
104
|
+
},
|
105
|
+
},
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
LOAD_BALANCER_SERVICE = {
|
110
|
+
type: Hash,
|
111
|
+
allowed_empty: true,
|
112
|
+
internals: {
|
113
|
+
enabled: { type: 'boolean', required: false },
|
114
|
+
pools: {
|
115
|
+
type: Array,
|
116
|
+
required: true,
|
117
|
+
allowed_empty: true,
|
118
|
+
each_element_is: LOAD_BALANCER_POOL_ENTRY,
|
119
|
+
},
|
120
|
+
virtual_servers: {
|
121
|
+
type: Array,
|
122
|
+
required: true,
|
123
|
+
allowed_empty: true,
|
124
|
+
each_element_is: LOAD_BALANCER_VIRTUAL_SERVER_ENTRY,
|
125
|
+
},
|
126
|
+
}
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module Schema
|
3
|
+
|
4
|
+
NAT_RULE = {
|
5
|
+
type: Hash,
|
6
|
+
internals: {
|
7
|
+
id: {type: 'string_or_number', required: false},
|
8
|
+
enabled: {type: 'boolean', required: false},
|
9
|
+
rule_type: { type: 'enum', required: true, acceptable_values: ['SNAT', 'DNAT' ]},
|
10
|
+
description: {type: 'string', required: false, allowed_empty: true},
|
11
|
+
network_id: {type: 'string', required: true},
|
12
|
+
original_ip: {type: 'ip_address_range', required: true},
|
13
|
+
original_port: {type: 'string', required: false},
|
14
|
+
translated_ip: {type: 'ip_address_range', required: true},
|
15
|
+
translated_port: {type: 'string', required: false},
|
16
|
+
protocol: {type: 'enum', required: false, acceptable_values: ['tcp', 'udp', 'icmp', 'tcp+udp', 'any']},
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
NAT_SERVICE = {
|
21
|
+
type: Hash,
|
22
|
+
allowed_empty: true,
|
23
|
+
required: false,
|
24
|
+
internals: {
|
25
|
+
enabled: {type: 'boolean', required: false},
|
26
|
+
nat_rules: {
|
27
|
+
type: Array,
|
28
|
+
required: false,
|
29
|
+
allowed_empty: true,
|
30
|
+
each_element_is: NAT_RULE
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
data/spec/erb_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
class ErbHelper
|
2
|
+
def self.convert_erb_template_to_yaml test_namespace, input_erb_config
|
3
|
+
input_erb_config = input_erb_config
|
4
|
+
e = ERB.new(File.open(input_erb_config).read)
|
5
|
+
output_yaml_config = File.join(File.dirname(input_erb_config), "output_#{Time.now.strftime('%s')}.yaml")
|
6
|
+
File.open(output_yaml_config, 'w') { |f|
|
7
|
+
f.write e.result(OpenStruct.new(test_namespace).instance_eval { binding })
|
8
|
+
}
|
9
|
+
output_yaml_config
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
gateway: <%= edge_gateway_name %>
|
3
|
+
firewall_service:
|
4
|
+
policy: drop
|
5
|
+
log_default_action: true
|
6
|
+
firewall_rules:
|
7
|
+
- enabled: true
|
8
|
+
description: 'A rule'
|
9
|
+
policy: allow
|
10
|
+
protocols: 'tcp'
|
11
|
+
destination_port_range: Any
|
12
|
+
destination_ip: 10.10.1.2
|
13
|
+
source_port_range: Any
|
14
|
+
source_ip: 192.0.2.2
|
15
|
+
- enabled: true
|
16
|
+
destination_ip: '10.10.1.3-10.10.1.5'
|
17
|
+
source_ip: 192.0.2.2/24
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
gateway: <%= edge_gateway_name %>
|
3
|
+
firewall_service:
|
4
|
+
policy: drop
|
5
|
+
log_default_action: true
|
6
|
+
firewall_rules:
|
7
|
+
- enabled: true
|
8
|
+
description: 'A rule'
|
9
|
+
policy: allow
|
10
|
+
protocols: 'tcp'
|
11
|
+
destination_port_range: Any
|
12
|
+
destination_ip: 10.10.1.2
|
13
|
+
source_port_range: Any
|
14
|
+
source_ip: 192.0.2.2
|
15
|
+
- enabled: true
|
16
|
+
destination_ip: '10.10.1.3-10.10.1.6'
|
17
|
+
source_ip: 192.0.2.2/24
|