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 coverage report shows not-our-code results, add it here
10 'Anchor[java::begin:]',
11 'Archive::Download[opendaylight.tar.gz]',
12 'Archive::Download[opendaylight-systemd.tar.gz]',
13 'Archive::Extract[opendaylight]',
14 'Archive::Extract[opendaylight-systemd]',
15 'Class[Java::Config]',
16 'Class[Java::Params]',
17 'Class[Stdlib::Stages]',
19 'Exec[download archive opendaylight.tar.gz and check sum]',
20 'Exec[download archive opendaylight-systemd.tar.gz and check sum]',
21 'Exec[opendaylight unpack]',
22 'Exec[opendaylight-systemd unpack]',
23 'Exec[rm-on-error-opendaylight.tar.gz]',
24 'Exec[rm-on-error-opendaylight-systemd.tar.gz]',
25 'Exec[reload_systemd_units]',
26 'Exec[update-java-alternatives]',
30 'Stage[deploy_infra]',
35 RSpec::Puppet::Coverage.filters.push(*custom_filters)
38 # NB: This is a library of helper fns used by the rspec-puppet tests
41 # Tests that are common to all possible configurations
43 # Confirm that module compiles
45 it { should compile.with_all_deps }
47 # Confirm presence of classes
48 it { should contain_class('opendaylight') }
49 it { should contain_class('opendaylight::params') }
50 it { should contain_class('opendaylight::install') }
51 it { should contain_class('opendaylight::config') }
52 it { should contain_class('opendaylight::service') }
54 # Confirm relationships between classes
55 it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
56 it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
57 it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
58 it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
59 it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
60 it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
62 # Confirm presence of generic resources
63 it { should contain_service('opendaylight') }
64 it { should contain_file('org.apache.karaf.features.cfg') }
66 # Confirm properties of generic resources
67 # NB: These hashes don't work with Ruby 1.8.7, but we
68 # don't support 1.8.7 so that's okay. See issue #36.
70 should contain_service('opendaylight').with(
71 'ensure' => 'running',
73 'hasstatus' => 'true',
74 'hasrestart' => 'true',
78 should contain_file('org.apache.karaf.features.cfg').with(
80 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
87 # Shared tests that specialize in testing Karaf feature installs
88 def karaf_feature_tests(options = {})
90 # NB: This default list should be the same as the one in opendaylight::params
91 # TODO: Remove this possible source of bugs^^
92 default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management'])
93 extra_features = options.fetch(:extra_features, [])
95 # The order of this list concat matters
96 features = default_features + extra_features
97 features_csv = features.join(',')
99 # Confirm properties of Karaf features config file
100 # NB: These hashes don't work with Ruby 1.8.7, but we
101 # don't support 1.8.7 so that's okay. See issue #36.
103 should contain_file('org.apache.karaf.features.cfg').with(
105 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
111 should contain_file_line('featuresBoot').with(
112 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
113 'line' => "featuresBoot=#{features_csv}",
114 'match' => '^featuresBoot=.*$',
119 # Shared tests that specialize in testing ODL's REST port config
120 def odl_rest_port_tests(options = {})
122 # NB: This default value should be the same as one in opendaylight::params
123 # TODO: Remove this possible source of bugs^^
124 odl_rest_port = options.fetch(:odl_rest_port, 8080)
126 # Confirm properties of ODL REST port config file
127 # NB: These hashes don't work with Ruby 1.8.7, but we
128 # don't support 1.8.7 so that's okay. See issue #36.
130 should contain_file('jetty.xml').with(
132 'path' => '/opt/opendaylight/etc/jetty.xml',
135 'content' => /Property name="jetty.port" default="#{odl_rest_port}"/
140 def log_level_tests(options = {})
142 # NB: This default value should be the same as one in opendaylight::params
143 # TODO: Remove this possible source of bugs^^
144 log_levels = options.fetch(:log_levels, {})
147 # Should contain log level config file
149 should_not contain_file_line('logger-org.opendaylight.ovsdb')
152 # Verify each custom log level config entry
153 log_levels.each_pair do |logger, level|
155 should contain_file_line("logger-#{logger}").with(
156 'ensure' => 'present',
157 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
158 'line' => "log4j.logger.#{logger}=#{level}",
165 def enable_ha_tests(options = {})
167 enable_ha = options.fetch(:enable_ha, false)
168 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
169 ha_node_ips = options.fetch(:ha_node_ips, [])
170 ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
172 ha_node_count = ha_node_ips.size
174 if (enable_ha) && (ha_node_count < 2)
175 # Check for HA_NODE_COUNT < 2
176 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
180 ha_node_index = ha_node_ips.index(odl_bind_ip)
182 should contain_file('akka.conf').with(
183 'path' => '/opt/opendaylight/configuration/initial/akka.conf',
187 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
191 ha_db_modules.each do |mod, urn|
192 it { should contain_file('module-shards.conf').with(
193 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf',
197 'content' => /name = "#{mod}"/
200 it { should contain_file('modules.conf').with(
201 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
207 it { should contain_file('modules.conf').with(
208 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
212 'content' => /name = "#{mod}"/,
218 should_not contain_file('akka.conf')
219 should_not contain_file('module-shards.conf')
220 should_not contain_file('modules.conf')
225 def rpm_install_tests(options = {})
227 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
228 java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
230 # Default to CentOS 7 Yum repo URL
232 # Confirm presence of RPM-related resources
233 it { should contain_yumrepo(rpm_repo) }
234 it { should contain_package('opendaylight') }
236 # Confirm relationships between RPM-related resources
237 it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
238 it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
240 # Confirm properties of RPM-related resources
241 # NB: These hashes don't work with Ruby 1.8.7, but we
242 # don't support 1.8.7 so that's okay. See issue #36.
244 should contain_yumrepo(rpm_repo).with(
247 'descr' => 'OpenDaylight SDN Controller',
248 'baseurl' => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
252 should contain_package('opendaylight').with(
253 'ensure' => 'present',
258 should contain_file_line('java_options_systemd').with(
259 'ensure' => 'present',
260 'path' => '/usr/lib/systemd/system/opendaylight.service',
261 'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
262 'after' => 'ExecStart=/opt/opendaylight/bin/start',
267 def deb_install_tests(options = {})
269 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
271 # Confirm the presence of Deb-related resources
272 it { should contain_apt__ppa(deb_repo) }
273 it { should contain_package('opendaylight') }
275 # Confirm relationships between Deb-related resources
276 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
277 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
279 # Confirm presence of Deb-related resources
281 should contain_package('opendaylight').with(
282 'ensure' => 'present',
287 # Shared tests for unsupported OSs
288 def unsupported_os_tests(options = {})
290 expected_msg = options.fetch(:expected_msg)
291 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
293 # Confirm that classes fail on unsupported OSs
294 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
295 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
296 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
297 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
299 # Confirm that other resources fail on unsupported OSs
300 it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
301 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
302 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
303 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
306 # Shared tests that specialize in testing security group mode
307 def enable_sg_tests(sg_mode='stateful', os_release)
309 # NB: This default value should be the same as one in opendaylight::params
310 # TODO: Remove this possible source of bugs^^
312 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
313 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
314 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
315 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
317 if os_release != '7.3' and sg_mode == 'stateful'
318 # Confirm sg_mode becomes learn
320 should contain_file('netvirt-aclservice-config.xml').with(
322 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
329 # Confirm other sg_mode is passed correctly
331 should contain_file('netvirt-aclservice-config.xml').with(
333 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
336 'content' => /#{sg_mode}/
342 # Shared tests that specialize in testing VPP routing node config
343 def vpp_routing_node_tests(options = {})
345 # NB: This default list should be the same as the one in opendaylight::params
346 # TODO: Remove this possible source of bugs^^
347 routing_node = options.fetch(:routing_node, '')
349 if routing_node.empty?
350 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
351 it { should_not contain_file_line('routing-node') }
353 # Confirm properties of Karaf config file
354 # NB: These hashes don't work with Ruby 1.8.7, but we
355 # don't support 1.8.7 so that's okay. See issue #36.
357 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
359 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
365 should contain_file_line('routing-node').with(
366 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
367 'line' => "routing-node=#{routing_node}",
368 'match' => '^routing-node=.*$',
374 # ODL username/password tests
375 def username_password_tests(username, password)
378 should contain_odl_user(username).with(
379 :password => password