00b21fd0ef46f75b7c506cbfdb51290f46b2ee60
[integration/packaging/puppet-opendaylight.git] / spec / spec_helper.rb
1 require 'puppetlabs_spec_helper/module_spec_helper'
2 require 'rspec-puppet-facts'
3 include RspecPuppetFacts
4
5 # Customize filters to ignore 3rd-party code
6 # If the rspec coverage report shows not-our-code results, add it here
7 custom_filters = [
8 ]
9 RSpec::Puppet::Coverage.filters.push(*custom_filters)
10
11 #
12 # NB: This is a library of helper fns used by the rspec-puppet tests
13 #
14
15 # Tests that are common to all possible configurations
16 def generic_tests()
17   # Confirm that module compiles
18   it { should compile }
19   it { should compile.with_all_deps }
20
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') }
27
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]') }
35
36   # Confirm presence of generic resources
37   it { should contain_service('opendaylight') }
38   it { should contain_file('org.apache.karaf.features.cfg') }
39
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.
43   it {
44     should contain_service('opendaylight').with(
45       'ensure'      => 'running',
46       'enable'      => 'true',
47       'hasstatus'   => 'true',
48       'hasrestart'  => 'true',
49     )
50   }
51   it {
52     should contain_file('org.apache.karaf.features.cfg').with(
53       'ensure'      => 'file',
54       'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
55       'owner'   => 'odl',
56       'group'   => 'odl',
57     )
58   }
59 end
60
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)
66
67   it {
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.*$',
72     )
73   }
74   it {
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.*$',
79     )
80   }
81 end
82
83 # Shared tests that specialize in testing Karaf feature installs
84 def karaf_feature_tests(options = {})
85   # Extract params
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, [])
90
91   # The order of this list concat matters
92   features = default_features + extra_features
93   features_csv = features.join(',')
94
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.
98   it {
99     should contain_file('org.apache.karaf.features.cfg').with(
100       'ensure'      => 'file',
101       'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
102       'owner'   => 'odl',
103       'group'   => 'odl',
104     )
105   }
106   it {
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=.*$',
111     )
112   }
113 end
114
115 # Shared tests that specialize in testing ODL's REST port config
116 def odl_rest_port_tests(options = {})
117   # Extract params
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
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.
125   it {
126     should contain_file('jetty.xml').with(
127       'ensure'      => 'file',
128       'path'        => '/opt/opendaylight/etc/jetty.xml',
129       'owner'   => 'odl',
130       'group'   => 'odl',
131       'content'     => /Property name="jetty.port" default="#{odl_rest_port}"/
132     )
133   }
134 end
135
136 def log_level_tests(options = {})
137   # Extract params
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, {})
141
142   if log_levels.empty?
143     # Should contain log level config file
144     it {
145       should_not contain_file_line('logger-org.opendaylight.ovsdb')
146     }
147   else
148     # Verify each custom log level config entry
149     log_levels.each_pair do |logger, level|
150       it {
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}",
155         )
156       }
157     end
158   end
159 end
160
161 def enable_ha_tests(options = {})
162   # Extract params
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 })
167   # HA_NODE_IPS size
168   ha_node_count = ha_node_ips.size
169
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")
173   end
174
175   if enable_ha
176     ha_node_index = ha_node_ips.index(odl_bind_ip)
177     it {
178       should contain_file('akka.conf').with(
179         'path'    => '/opt/opendaylight/configuration/initial/akka.conf',
180         'ensure'  => 'file',
181         'owner'   => 'odl',
182         'group'   => 'odl',
183         'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
184       )
185     }
186
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',
190         'ensure'  => 'file',
191         'owner'   => 'odl',
192         'group'   => 'odl',
193         'content' => /name = "#{mod}"/
194       )}
195       if mod == 'default'
196         it { should contain_file('modules.conf').with(
197           'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
198           'ensure'  => 'file',
199           'owner'   => 'odl',
200           'group'   => 'odl'
201         )}
202       else
203         it { should contain_file('modules.conf').with(
204           'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
205           'ensure'  => 'file',
206           'owner'   => 'odl',
207           'group'   => 'odl',
208           'content' => /name = "#{mod}"/,
209         )}
210       end
211     end
212   else
213     it {
214       should_not contain_file('akka.conf')
215       should_not contain_file('module-shards.conf')
216       should_not contain_file('modules.conf')
217       }
218   end
219 end
220
221 def rpm_install_tests(options = {})
222   # Extract params
223   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
224   java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
225
226   # Default to CentOS 7 Yum repo URL
227
228   # Confirm presence of RPM-related resources
229   it { should contain_yumrepo(rpm_repo) }
230   it { should contain_package('opendaylight') }
231
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]') }
235
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.
239   it {
240     should contain_yumrepo(rpm_repo).with(
241       'enabled'     => '1',
242       'gpgcheck'    => '0',
243       'descr'       => 'OpenDaylight SDN Controller',
244       'baseurl'     => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
245     )
246   }
247   it {
248     should contain_package('opendaylight').with(
249       'ensure'   => 'present',
250     )
251   }
252
253   it {
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',
259     )
260   }
261 end
262
263 def deb_install_tests(options = {})
264   # Extract params
265   deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
266
267   # Confirm the presence of Deb-related resources
268   it { should contain_apt__ppa(deb_repo) }
269   it { should contain_package('opendaylight') }
270
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]') }
274
275   # Confirm presence of Deb-related resources
276   it {
277     should contain_package('opendaylight').with(
278       'ensure'   => 'present',
279     )
280   }
281 end
282
283 # Shared tests for unsupported OSs
284 def unsupported_os_tests(options = {})
285   # Extract params
286   expected_msg = options.fetch(:expected_msg)
287   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
288
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}/) }
294
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}/) }
300 end
301
302 # Shared tests that specialize in testing security group mode
303 def enable_sg_tests(sg_mode='stateful', os_release)
304   # Extract params
305   # NB: This default value should be the same as one in opendaylight::params
306   # TODO: Remove this possible source of bugs^^
307
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')}
312
313   if os_release != '7.3' and sg_mode == 'stateful'
314     # Confirm sg_mode becomes learn
315     it {
316       should contain_file('netvirt-aclservice-config.xml').with(
317         'ensure'      => 'file',
318         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
319         'owner'   => 'odl',
320         'group'   => 'odl',
321         'content'     => /learn/
322       )
323     }
324   else
325     # Confirm other sg_mode is passed correctly
326     it {
327       should contain_file('netvirt-aclservice-config.xml').with(
328         'ensure'      => 'file',
329         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
330         'owner'   => 'odl',
331         'group'   => 'odl',
332         'content'     => /#{sg_mode}/
333       )
334     }
335   end
336 end
337
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')}
344
345   # Confirm snat_mechanism
346   it {
347     should contain_file('netvirt-natservice-config.xml').with(
348       'ensure'      => 'file',
349       'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
350       'owner'   => 'odl',
351       'group'   => 'odl',
352       'content'     =>  /<nat-mode>#{snat_mechanism}<\/nat-mode>/
353       )
354     }
355 end
356
357 # Shared tests that specialize in testing SFC Config
358 def sfc_tests()
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')}
363
364   it {
365     should contain_file('netvirt-elanmanager-config.xml').with(
366       'ensure'  => 'file',
367       'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
368       'owner'   => 'odl',
369       'group'   => 'odl',
370       'source'  => 'puppet:///modules/opendaylight/netvirt-elanmanager-config.xml'
371       )
372     should contain_file('genius-itm-config.xml').with(
373       'ensure'  => 'file',
374       'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
375       'owner'   => 'odl',
376       'group'   => 'odl',
377       'source'  => 'puppet:///modules/opendaylight/genius-itm-config.xml'
378       )
379     }
380 end
381
382 # Shared tests that specialize in testing VPP routing node config
383 def vpp_routing_node_tests(options = {})
384   # Extract params
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, '')
388
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') }
392   else
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.
396     it {
397       should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
398         'ensure'      => 'file',
399         'path'        => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
400         'owner'   => 'odl',
401         'group'   => 'odl',
402       )
403     }
404     it {
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=.*$',
409       )
410     }
411   end
412 end
413
414 # ODL username/password tests
415 def username_password_tests(username, password)
416
417   it {
418     should contain_odl_user(username).with(
419       :password => password
420     )
421   }
422 end