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[Configure ODL OVSDB Clustering]',
20 'Exec[download archive opendaylight.tar.gz and check sum]',
21 'Exec[download archive opendaylight-systemd.tar.gz and check sum]',
22 'Exec[opendaylight unpack]',
23 'Exec[opendaylight-systemd unpack]',
24 'Exec[rm-on-error-opendaylight.tar.gz]',
25 'Exec[rm-on-error-opendaylight-systemd.tar.gz]',
26 'Exec[reload_systemd_units]',
27 'Exec[update-java-alternatives]',
31 'Stage[deploy_infra]',
36 RSpec::Puppet::Coverage.filters.push(*custom_filters)
39 # NB: This is a library of helper fns used by the rspec-puppet tests
42 # Tests that are common to all possible configurations
44 # Confirm that module compiles
46 it { should compile.with_all_deps }
48 # Confirm presence of classes
49 it { should contain_class('opendaylight') }
50 it { should contain_class('opendaylight::params') }
51 it { should contain_class('opendaylight::install') }
52 it { should contain_class('opendaylight::config') }
53 it { should contain_class('opendaylight::service') }
55 # Confirm relationships between classes
56 it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
57 it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
58 it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
59 it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
60 it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
61 it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
63 # Confirm presence of generic resources
64 it { should contain_service('opendaylight') }
65 it { should contain_file('org.apache.karaf.features.cfg') }
67 # Confirm properties of generic resources
68 # NB: These hashes don't work with Ruby 1.8.7, but we
69 # don't support 1.8.7 so that's okay. See issue #36.
71 should contain_service('opendaylight').with(
72 'ensure' => 'running',
74 'hasstatus' => 'true',
75 'hasrestart' => 'true',
79 should contain_file('org.apache.karaf.features.cfg').with(
81 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
88 # Shared tests that specialize in testing Karaf feature installs
89 def karaf_feature_tests(options = {})
91 # NB: This default list should be the same as the one in opendaylight::params
92 # TODO: Remove this possible source of bugs^^
93 default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management'])
94 extra_features = options.fetch(:extra_features, [])
96 # The order of this list concat matters
97 features = default_features + extra_features
98 features_csv = features.join(',')
100 # Confirm properties of Karaf features config file
101 # NB: These hashes don't work with Ruby 1.8.7, but we
102 # don't support 1.8.7 so that's okay. See issue #36.
104 should contain_file('org.apache.karaf.features.cfg').with(
106 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
112 should contain_file_line('featuresBoot').with(
113 'path' => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
114 'line' => "featuresBoot=#{features_csv}",
115 'match' => '^featuresBoot=.*$',
120 # Shared tests that specialize in testing ODL's REST port config
121 def odl_rest_port_tests(options = {})
123 # NB: This default value should be the same as one in opendaylight::params
124 # TODO: Remove this possible source of bugs^^
125 odl_rest_port = options.fetch(:odl_rest_port, 8080)
127 # Confirm properties of ODL REST port config file
128 # NB: These hashes don't work with Ruby 1.8.7, but we
129 # don't support 1.8.7 so that's okay. See issue #36.
131 should contain_file('jetty.xml').with(
133 'path' => '/opt/opendaylight/etc/jetty.xml',
136 'content' => /Property name="jetty.port" default="#{odl_rest_port}"/
141 def log_level_tests(options = {})
143 # NB: This default value should be the same as one in opendaylight::params
144 # TODO: Remove this possible source of bugs^^
145 log_levels = options.fetch(:log_levels, {})
148 # Should contain log level config file
150 should contain_file('org.ops4j.pax.logging.cfg').with(
152 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
157 # Should not contain custom log level config
159 should_not contain_file('org.ops4j.pax.logging.cfg').with(
161 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
164 'content' => /# Log level config added by puppet-opendaylight/
168 # Should contain log level config file
170 should contain_file('org.ops4j.pax.logging.cfg').with(
172 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
177 # Should contain custom log level config
179 should contain_file('org.ops4j.pax.logging.cfg').with(
181 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
184 'content' => /# Log level config added by puppet-opendaylight/
187 # Verify each custom log level config entry
188 log_levels.each_pair do |logger, level|
190 should contain_file('org.ops4j.pax.logging.cfg').with(
192 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
195 'content' => /^log4j.logger.#{logger} = #{level}/
202 def enable_ha_tests(options = {})
204 enable_ha = options.fetch(:enable_ha, false)
205 ha_node_ips = options.fetch(:ha_node_ips, [])
206 ha_node_index = options.fetch(:ha_node_index, 0)
208 ha_node_count = ha_node_ips.size
210 if (enable_ha) && (ha_node_count < 2)
211 # Check for HA_NODE_COUNT < 2
212 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
216 def rpm_install_tests(options = {})
218 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
219 java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
221 # Default to CentOS 7 Yum repo URL
223 # Confirm presence of RPM-related resources
224 it { should contain_yumrepo(rpm_repo) }
225 it { should contain_package('opendaylight') }
227 # Confirm relationships between RPM-related resources
228 it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
229 it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
231 # Confirm properties of RPM-related resources
232 # NB: These hashes don't work with Ruby 1.8.7, but we
233 # don't support 1.8.7 so that's okay. See issue #36.
235 should contain_yumrepo(rpm_repo).with(
238 'descr' => 'OpenDaylight SDN Controller',
239 'baseurl' => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
243 should contain_package('opendaylight').with(
244 'ensure' => 'present',
249 should contain_file_line('java_options_systemd').with(
250 'ensure' => 'present',
251 'path' => '/usr/lib/systemd/system/opendaylight.service',
252 'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
253 'after' => 'ExecStart=/opt/opendaylight/bin/start',
258 def deb_install_tests(options = {})
260 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/boron')
262 # Confirm the presence of Deb-related resources
263 it { should contain_apt__ppa(deb_repo) }
264 it { should contain_package('opendaylight') }
266 # Confirm relationships between Deb-related resources
267 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
268 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
270 # Confirm presence of Deb-related resources
272 should contain_package('opendaylight').with(
273 'ensure' => 'present',
278 # Shared tests for unsupported OSs
279 def unsupported_os_tests(options = {})
281 expected_msg = options.fetch(:expected_msg)
282 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
284 # Confirm that classes fail on unsupported OSs
285 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
286 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
287 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
288 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
290 # Confirm that other resources fail on unsupported OSs
291 it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
292 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
293 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
294 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
297 # Shared tests that specialize in testing security group mode
298 def enable_sg_tests(sg_mode='stateful', os_release)
300 # NB: This default value should be the same as one in opendaylight::params
301 # TODO: Remove this possible source of bugs^^
303 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
304 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
305 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
306 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
308 if os_release != '7.3' and sg_mode == 'stateful'
309 # Confirm sg_mode becomes learn
311 should contain_file('netvirt-aclservice-config.xml').with(
313 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
320 # Confirm other sg_mode is passed correctly
322 should contain_file('netvirt-aclservice-config.xml').with(
324 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
327 'content' => /#{sg_mode}/
333 # Shared tests that specialize in testing VPP routing node config
334 def vpp_routing_node_tests(options = {})
336 # NB: This default list should be the same as the one in opendaylight::params
337 # TODO: Remove this possible source of bugs^^
338 routing_node = options.fetch(:routing_node, '')
340 if routing_node.empty?
341 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
342 it { should_not contain_file_line('routing-node') }
344 # Confirm properties of Karaf config file
345 # NB: These hashes don't work with Ruby 1.8.7, but we
346 # don't support 1.8.7 so that's okay. See issue #36.
348 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
350 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
356 should contain_file_line('routing-node').with(
357 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
358 'line' => "routing-node=#{routing_node}",
359 'match' => '^routing-node=.*$',