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)
121 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
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('ODL REST Port')
129 if not odl_bind_ip.eql? '0.0.0.0'
131 should contain_augeas('ODL REST IP')
132 should contain_file_line('org.ops4j.pax.web.cfg').with(
133 'path' => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
134 'line' => "org.ops4j.pax.web.listening.addresses = #{odl_bind_ip}",
139 should_not contain_augeas('ODL REST IP')
144 def log_level_tests(options = {})
146 # NB: This default value should be the same as one in opendaylight::params
147 # TODO: Remove this possible source of bugs^^
148 log_levels = options.fetch(:log_levels, {})
151 # Should contain log level config file
153 should_not contain_file_line('logger-org.opendaylight.ovsdb')
156 # Verify each custom log level config entry
157 log_levels.each_pair do |logger, level|
159 should contain_file_line("logger-#{logger}").with(
160 'ensure' => 'present',
161 'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
162 'line' => "log4j.logger.#{logger}=#{level}",
169 def enable_ha_tests(options = {})
171 enable_ha = options.fetch(:enable_ha, false)
172 odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
173 ha_node_ips = options.fetch(:ha_node_ips, [])
174 ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
176 ha_node_count = ha_node_ips.size
178 if (enable_ha) && (ha_node_count < 2)
179 # Check for HA_NODE_COUNT < 2
180 fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
184 ha_node_index = ha_node_ips.index(odl_bind_ip)
186 should contain_file('akka.conf').with(
187 'path' => '/opt/opendaylight/configuration/initial/akka.conf',
191 'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
195 ha_db_modules.each do |mod, urn|
196 it { should contain_file('module-shards.conf').with(
197 'path' => '/opt/opendaylight/configuration/initial/module-shards.conf',
201 'content' => /name = "#{mod}"/
204 it { should contain_file('modules.conf').with(
205 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
211 it { should contain_file('modules.conf').with(
212 'path' => '/opt/opendaylight/configuration/initial/modules.conf',
216 'content' => /name = "#{mod}"/,
222 should_not contain_file('akka.conf')
223 should_not contain_file('module-shards.conf')
224 should_not contain_file('modules.conf')
229 def rpm_install_tests(options = {})
231 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
232 java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
234 # Default to CentOS 7 Yum repo URL
236 # Confirm presence of RPM-related resources
237 it { should contain_yumrepo(rpm_repo) }
238 it { should contain_package('opendaylight') }
240 # Confirm relationships between RPM-related resources
241 it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
242 it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
244 # Confirm properties of RPM-related resources
245 # NB: These hashes don't work with Ruby 1.8.7, but we
246 # don't support 1.8.7 so that's okay. See issue #36.
248 should contain_yumrepo(rpm_repo).with(
251 'descr' => 'OpenDaylight SDN Controller',
252 'baseurl' => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
256 should contain_package('opendaylight').with(
257 'ensure' => 'present',
262 should contain_file_line('java_options_systemd').with(
263 'ensure' => 'present',
264 'path' => '/usr/lib/systemd/system/opendaylight.service',
265 'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
266 'after' => 'ExecStart=/opt/opendaylight/bin/start',
271 def deb_install_tests(options = {})
273 deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
275 # Confirm the presence of Deb-related resources
276 it { should contain_apt__ppa(deb_repo) }
277 it { should contain_package('opendaylight') }
279 # Confirm relationships between Deb-related resources
280 it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
281 it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
283 # Confirm presence of Deb-related resources
285 should contain_package('opendaylight').with(
286 'ensure' => 'present',
291 # Shared tests for unsupported OSs
292 def unsupported_os_tests(options = {})
294 expected_msg = options.fetch(:expected_msg)
295 rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
297 # Confirm that classes fail on unsupported OSs
298 it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
299 it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
300 it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
301 it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
303 # Confirm that other resources fail on unsupported OSs
304 it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
305 it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
306 it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
307 it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
310 # Shared tests that specialize in testing security group mode
311 def enable_sg_tests(sg_mode='stateful', os_release)
313 # NB: This default value should be the same as one in opendaylight::params
314 # TODO: Remove this possible source of bugs^^
316 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
317 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
318 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
319 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
321 if os_release != '7.3' and sg_mode == 'stateful'
322 # Confirm sg_mode becomes learn
324 should contain_file('netvirt-aclservice-config.xml').with(
326 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
333 # Confirm other sg_mode is passed correctly
335 should contain_file('netvirt-aclservice-config.xml').with(
337 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
340 'content' => /#{sg_mode}/
346 # Shared tests that specialize in testing SNAT mechanism
347 def snat_mechanism_tests(snat_mechanism='controller')
348 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
349 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
350 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
351 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
353 # Confirm snat_mechanism
355 should contain_file('netvirt-natservice-config.xml').with(
357 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
360 'content' => /<nat-mode>#{snat_mechanism}<\/nat-mode>/
365 # Shared tests that specialize in testing SFC Config
367 it { should contain_file('/opt/opendaylight/etc/opendaylight') }
368 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
369 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
370 it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
373 should contain_file('netvirt-elanmanager-config.xml').with(
375 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
378 'source' => 'puppet:///modules/opendaylight/netvirt-elanmanager-config.xml'
380 should contain_file('genius-itm-config.xml').with(
382 'path' => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
385 'source' => 'puppet:///modules/opendaylight/genius-itm-config.xml'
390 # Shared tests that specialize in testing VPP routing node config
391 def vpp_routing_node_tests(options = {})
393 # NB: This default list should be the same as the one in opendaylight::params
394 # TODO: Remove this possible source of bugs^^
395 routing_node = options.fetch(:routing_node, '')
397 if routing_node.empty?
398 it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
399 it { should_not contain_file_line('routing-node') }
401 # Confirm properties of Karaf config file
402 # NB: These hashes don't work with Ruby 1.8.7, but we
403 # don't support 1.8.7 so that's okay. See issue #36.
405 should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
407 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
413 should contain_file_line('routing-node').with(
414 'path' => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
415 'line' => "routing-node=#{routing_node}",
416 'match' => '^routing-node=.*$',
422 # ODL username/password tests
423 def username_password_tests(username, password)
426 should contain_odl_user(username).with(
427 :password => password