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_augeas('jetty.xml')
130 def log_level_tests(options = {})
132 # NB: This default value should be the same as one in opendaylight::params
133 # TODO: Remove this possible source of bugs^^
134 log_levels = options.fetch(:log_levels, {})
137 # Should contain log level config file
139 should_not contain_file_line('logger-org.opendaylight.ovsdb')
142 # Verify each custom log level config entry
143 log_levels.each_pair do |logger, level|
145 should contain_file_line("logger-#{logger}").with(
146 'ensure' => 'present',
147 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
148 'line' => "log4j.logger.#{logger}=#{level}",
155 def enable_ha_tests(options = {})
157 enable_ha = options.fetch(:enable_ha, false)
158 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
159 ha_node_ips = options.fetch(:ha_node_ips, [])
160 ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
162 ha_node_count = ha_node_ips.size
164 if (enable_ha) && (ha_node_count < 2)
165 # Check for HA_NODE_COUNT < 2
166 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
170 ha_node_index = ha_node_ips.index(odl_bind_ip)
172 should contain_file('akka.conf').with(
173 'path' => '/opt/opendaylight/configuration/initial/akka.conf',
177 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
181 ha_db_modules.each do |mod, urn|
182 it { should contain_file('module-shards.conf').with(
183 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf',
187 'content' => /name = "#{mod}"/
190 it { should contain_file('modules.conf').with(
191 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
197 it { should contain_file('modules.conf').with(
198 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
202 'content' => /name = "#{mod}"/,
208 should_not contain_file('akka.conf')
209 should_not contain_file('module-shards.conf')
210 should_not contain_file('modules.conf')
215 def rpm_install_tests(options = {})
217 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
218 java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
220 # Default to CentOS 7 Yum repo URL
222 # Confirm presence of RPM-related resources
223 it { should contain_yumrepo(rpm_repo) }
224 it { should contain_package('opendaylight') }
226 # Confirm relationships between RPM-related resources
227 it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
228 it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
230 # Confirm properties of RPM-related resources
231 # NB: These hashes don't work with Ruby 1.8.7, but we
232 # don't support 1.8.7 so that's okay. See issue #36.
234 should contain_yumrepo(rpm_repo).with(
237 'descr' => 'OpenDaylight SDN Controller',
238 'baseurl' => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
242 should contain_package('opendaylight').with(
243 'ensure' => 'present',
248 should contain_file_line('java_options_systemd').with(
249 'ensure' => 'present',
250 'path' => '/usr/lib/systemd/system/opendaylight.service',
251 'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
252 'after' => 'ExecStart=/opt/opendaylight/bin/start',
257 def deb_install_tests(options = {})
259 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
261 # Confirm the presence of Deb-related resources
262 it { should contain_apt__ppa(deb_repo) }
263 it { should contain_package('opendaylight') }
265 # Confirm relationships between Deb-related resources
266 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
267 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
269 # Confirm presence of Deb-related resources
271 should contain_package('opendaylight').with(
272 'ensure' => 'present',
277 # Shared tests for unsupported OSs
278 def unsupported_os_tests(options = {})
280 expected_msg = options.fetch(:expected_msg)
281 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
283 # Confirm that classes fail on unsupported OSs
284 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
285 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
286 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
287 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
289 # Confirm that other resources fail on unsupported OSs
290 it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
291 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
292 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
293 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
296 # Shared tests that specialize in testing security group mode
297 def enable_sg_tests(sg_mode='stateful', os_release)
299 # NB: This default value should be the same as one in opendaylight::params
300 # TODO: Remove this possible source of bugs^^
302 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
303 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
304 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
305 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
307 if os_release != '7.3' and sg_mode == 'stateful'
308 # Confirm sg_mode becomes learn
310 should contain_file('netvirt-aclservice-config.xml').with(
312 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
319 # Confirm other sg_mode is passed correctly
321 should contain_file('netvirt-aclservice-config.xml').with(
323 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
326 'content' => /#{sg_mode}/
332 # Shared tests that specialize in testing SNAT mechanism
333 def snat_mechanism_tests(snat_mechanism='controller')
334 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
335 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
336 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
337 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
339 # Confirm snat_mechanism
341 should contain_file('netvirt-natservice-config.xml').with(
343 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
346 'content' => /<nat-mode>#{snat_mechanism}<\/nat-mode>/
351 # Shared tests that specialize in testing SFC Config
353 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
354 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
355 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
356 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
359 should contain_file('netvirt-elanmanager-config.xml').with(
361 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
364 'source' => 'puppet:///modules/opendaylight/netvirt-elanmanager-config.xml'
366 should contain_file('genius-itm-config.xml').with(
368 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
371 'source' => 'puppet:///modules/opendaylight/genius-itm-config.xml'
376 # Shared tests that specialize in testing VPP routing node config
377 def vpp_routing_node_tests(options = {})
379 # NB: This default list should be the same as the one in opendaylight::params
380 # TODO: Remove this possible source of bugs^^
381 routing_node = options.fetch(:routing_node, '')
383 if routing_node.empty?
384 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
385 it { should_not contain_file_line('routing-node') }
387 # Confirm properties of Karaf config file
388 # NB: These hashes don't work with Ruby 1.8.7, but we
389 # don't support 1.8.7 so that's okay. See issue #36.
391 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
393 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
399 should contain_file_line('routing-node').with(
400 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
401 'line' => "routing-node=#{routing_node}",
402 'match' => '^routing-node=.*$',
408 # ODL username/password tests
409 def username_password_tests(username, password)
412 should contain_odl_user(username).with(
413 :password => password