1 require 'puppetlabs_spec_helper/module_spec_helper'
2 require 'rspec-puppet-facts'
3 include RspecPuppetFacts
5 # Customize filters to ignore 3rd-party code
6 # If the rspec coverage report shows not-our-code results, add it here
9 RSpec::Puppet::Coverage.filters.push(*custom_filters)
12 # NB: This is a library of helper fns used by the rspec-puppet tests
15 # Tests that are common to all possible configurations
17 # Confirm that module compiles
19 it { should compile.with_all_deps }
21 # Confirm presence of classes
22 it { should contain_class('opendaylight') }
23 it { should contain_class('opendaylight::params') }
24 it { should contain_class('opendaylight::install') }
25 it { should contain_class('opendaylight::config') }
26 it { should contain_class('opendaylight::service') }
28 # Confirm relationships between classes
29 it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
30 it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
31 it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
32 it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
33 it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
34 it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
36 # Confirm presence of generic resources
37 it { should contain_service('opendaylight') }
38 it { should contain_file('org.apache.karaf.features.cfg') }
40 # Confirm properties of generic resources
41 # NB: These hashes don't work with Ruby 1.8.7, but we
42 # don't support 1.8.7 so that's okay. See issue #36.
44 should contain_service('opendaylight').with(
45 'ensure' => 'running',
47 'hasstatus' => 'true',
48 'hasrestart' => 'true',
52 should contain_file('org.apache.karaf.features.cfg').with(
54 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
61 # Shared tests that specialize in testing log file size and rollover
62 def log_file_settings(options = {})
63 # Extraxt params. The dafault value should be same as in opendaylight::params
64 log_max_size = options.fetch(:log_max_size, '10GB')
65 log_max_rollover = options.fetch(:log_max_rollover, 2)
68 should contain_file_line('logmaxsize').with(
69 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
70 'line' => "log4j.appender.out.maxFileSize=#{log_max_size}",
71 'match' => '^log4j.appender.out.maxFileSize.*$',
75 should contain_file_line('logmaxrollover').with(
76 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
77 'line' => "log4j.appender.out.maxBackupIndex=#{log_max_rollover}",
78 'match' => '^log4j.appender.out.maxBackupIndex.*$',
83 # Shared tests that specialize in testing Karaf feature installs
84 def karaf_feature_tests(options = {})
86 # NB: This default list should be the same as the one in opendaylight::params
87 # TODO: Remove this possible source of bugs^^
88 default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management'])
89 extra_features = options.fetch(:extra_features, [])
91 # The order of this list concat matters
92 features = default_features + extra_features
93 features_csv = features.join(',')
95 # Confirm properties of Karaf features config file
96 # NB: These hashes don't work with Ruby 1.8.7, but we
97 # don't support 1.8.7 so that's okay. See issue #36.
99 should contain_file('org.apache.karaf.features.cfg').with(
101 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
107 should contain_file_line('featuresBoot').with(
108 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
109 'line' => "featuresBoot=#{features_csv}",
110 'match' => '^featuresBoot=.*$',
115 # Shared tests that specialize in testing ODL's REST port config
116 def odl_rest_port_tests(options = {})
118 # NB: This default value should be the same as one in opendaylight::params
119 # TODO: Remove this possible source of bugs^^
120 odl_rest_port = options.fetch(:odl_rest_port, 8080)
122 # Confirm properties of ODL REST port config file
123 # NB: These hashes don't work with Ruby 1.8.7, but we
124 # don't support 1.8.7 so that's okay. See issue #36.
126 should contain_file('jetty.xml').with(
128 'path' => '/opt/opendaylight/etc/jetty.xml',
131 'content' => /Property name="jetty.port" default="#{odl_rest_port}"/
136 def log_level_tests(options = {})
138 # NB: This default value should be the same as one in opendaylight::params
139 # TODO: Remove this possible source of bugs^^
140 log_levels = options.fetch(:log_levels, {})
143 # Should contain log level config file
145 should_not contain_file_line('logger-org.opendaylight.ovsdb')
148 # Verify each custom log level config entry
149 log_levels.each_pair do |logger, level|
151 should contain_file_line("logger-#{logger}").with(
152 'ensure' => 'present',
153 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
154 'line' => "log4j.logger.#{logger}=#{level}",
161 def enable_ha_tests(options = {})
163 enable_ha = options.fetch(:enable_ha, false)
164 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
165 ha_node_ips = options.fetch(:ha_node_ips, [])
166 ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
168 ha_node_count = ha_node_ips.size
170 if (enable_ha) && (ha_node_count < 2)
171 # Check for HA_NODE_COUNT < 2
172 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
176 ha_node_index = ha_node_ips.index(odl_bind_ip)
178 should contain_file('akka.conf').with(
179 'path' => '/opt/opendaylight/configuration/initial/akka.conf',
183 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
187 ha_db_modules.each do |mod, urn|
188 it { should contain_file('module-shards.conf').with(
189 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf',
193 'content' => /name = "#{mod}"/
196 it { should contain_file('modules.conf').with(
197 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
203 it { should contain_file('modules.conf').with(
204 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
208 'content' => /name = "#{mod}"/,
214 should_not contain_file('akka.conf')
215 should_not contain_file('module-shards.conf')
216 should_not contain_file('modules.conf')
221 def rpm_install_tests(options = {})
223 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
224 java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
226 # Default to CentOS 7 Yum repo URL
228 # Confirm presence of RPM-related resources
229 it { should contain_yumrepo(rpm_repo) }
230 it { should contain_package('opendaylight') }
232 # Confirm relationships between RPM-related resources
233 it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
234 it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
236 # Confirm properties of RPM-related resources
237 # NB: These hashes don't work with Ruby 1.8.7, but we
238 # don't support 1.8.7 so that's okay. See issue #36.
240 should contain_yumrepo(rpm_repo).with(
243 'descr' => 'OpenDaylight SDN Controller',
244 'baseurl' => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
248 should contain_package('opendaylight').with(
249 'ensure' => 'present',
254 should contain_file_line('java_options_systemd').with(
255 'ensure' => 'present',
256 'path' => '/usr/lib/systemd/system/opendaylight.service',
257 'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
258 'after' => 'ExecStart=/opt/opendaylight/bin/start',
263 def deb_install_tests(options = {})
265 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
267 # Confirm the presence of Deb-related resources
268 it { should contain_apt__ppa(deb_repo) }
269 it { should contain_package('opendaylight') }
271 # Confirm relationships between Deb-related resources
272 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
273 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
275 # Confirm presence of Deb-related resources
277 should contain_package('opendaylight').with(
278 'ensure' => 'present',
283 # Shared tests for unsupported OSs
284 def unsupported_os_tests(options = {})
286 expected_msg = options.fetch(:expected_msg)
287 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
289 # Confirm that classes fail on unsupported OSs
290 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
291 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
292 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
293 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
295 # Confirm that other resources fail on unsupported OSs
296 it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
297 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
298 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
299 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
302 # Shared tests that specialize in testing security group mode
303 def enable_sg_tests(sg_mode='stateful', os_release)
305 # NB: This default value should be the same as one in opendaylight::params
306 # TODO: Remove this possible source of bugs^^
308 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
309 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
310 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
311 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
313 if os_release != '7.3' and sg_mode == 'stateful'
314 # Confirm sg_mode becomes learn
316 should contain_file('netvirt-aclservice-config.xml').with(
318 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
325 # Confirm other sg_mode is passed correctly
327 should contain_file('netvirt-aclservice-config.xml').with(
329 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
332 'content' => /#{sg_mode}/
338 # Shared tests that specialize in testing SNAT mechanism
339 def snat_mechanism_tests(snat_mechanism='controller')
340 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
341 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
342 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
343 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
345 # Confirm snat_mechanism
347 should contain_file('netvirt-natservice-config.xml').with(
349 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
352 'content' => /<nat-mode>#{snat_mechanism}<\/nat-mode>/
357 # Shared tests that specialize in testing SFC Config
359 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
360 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
361 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
362 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
365 should contain_file('netvirt-elanmanager-config.xml').with(
367 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
370 'source' => 'puppet:///modules/opendaylight/netvirt-elanmanager-config.xml'
372 should contain_file('genius-itm-config.xml').with(
374 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
377 'source' => 'puppet:///modules/opendaylight/genius-itm-config.xml'
382 # Shared tests that specialize in testing VPP routing node config
383 def vpp_routing_node_tests(options = {})
385 # NB: This default list should be the same as the one in opendaylight::params
386 # TODO: Remove this possible source of bugs^^
387 routing_node = options.fetch(:routing_node, '')
389 if routing_node.empty?
390 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
391 it { should_not contain_file_line('routing-node') }
393 # Confirm properties of Karaf config file
394 # NB: These hashes don't work with Ruby 1.8.7, but we
395 # don't support 1.8.7 so that's okay. See issue #36.
397 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
399 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
405 should contain_file_line('routing-node').with(
406 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
407 'line' => "routing-node=#{routing_node}",
408 'match' => '^routing-node=.*$',
414 # ODL username/password tests
415 def username_password_tests(username, password)
418 should contain_odl_user(username).with(
419 :password => password