7bf984d30f385e9ab4ae5eae53c06f7cfaf60baf
[integration/packaging/puppet-opendaylight.git] / spec / spec_helper.rb
1 require 'puppetlabs_spec_helper/module_spec_helper'
2
3 # Customize filters to ignore 3rd-party code
4 # If the coverage report shows not-our-code results, add it here
5 custom_filters = [
6   'Anchor[java::end]',
7   'Stage[setup]',
8   'Anchor[java::begin:]',
9   'Archive::Download[opendaylight.tar.gz]',
10   'Archive::Download[opendaylight-systemd.tar.gz]',
11   'Archive::Extract[opendaylight]',
12   'Archive::Extract[opendaylight-systemd]',
13   'Class[Java::Config]',
14   'Class[Java::Params]',
15   'Class[Stdlib::Stages]',
16   'Class[Stdlib]',
17   'Exec[Configure ODL OVSDB Clustering]',
18   'Exec[download archive opendaylight.tar.gz and check sum]',
19   'Exec[download archive opendaylight-systemd.tar.gz and check sum]',
20   'Exec[opendaylight unpack]',
21   'Exec[opendaylight-systemd unpack]',
22   'Exec[rm-on-error-opendaylight.tar.gz]',
23   'Exec[rm-on-error-opendaylight-systemd.tar.gz]',
24   'Exec[reload_systemd_units]',
25   'Exec[update-java-alternatives]',
26   'Package[curl]',
27   'Stage[deploy]',
28   'Stage[deploy_app]',
29   'Stage[deploy_infra]',
30   'Stage[runtime]',
31   'Stage[setup_app]',
32   'Stage[setup_infra]',
33 ]
34 RSpec::Puppet::Coverage.filters.push(*custom_filters)
35
36 #
37 # NB: This is a library of helper fns used by the rspec-puppet tests
38 #
39
40 # Tests that are common to all possible configurations
41 def generic_tests()
42   # Confirm that module compiles
43   it { should compile }
44   it { should compile.with_all_deps }
45
46   # Confirm presence of classes
47   it { should contain_class('opendaylight') }
48   it { should contain_class('opendaylight::params') }
49   it { should contain_class('opendaylight::install') }
50   it { should contain_class('opendaylight::config') }
51   it { should contain_class('opendaylight::service') }
52
53   # Confirm relationships between classes
54   it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
55   it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
56   it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
57   it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
58   it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
59   it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
60
61   # Confirm presence of generic resources
62   it { should contain_service('opendaylight') }
63   it { should contain_file('org.apache.karaf.features.cfg') }
64
65   # Confirm properties of generic resources
66   # NB: These hashes don't work with Ruby 1.8.7, but we
67   #   don't support 1.8.7 so that's okay. See issue #36.
68   it {
69     should contain_service('opendaylight').with(
70       'ensure'      => 'running',
71       'enable'      => 'true',
72       'hasstatus'   => 'true',
73       'hasrestart'  => 'true',
74     )
75   }
76   it {
77     should contain_file('org.apache.karaf.features.cfg').with(
78       'ensure'      => 'file',
79       'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
80       'owner'   => 'odl',
81       'group'   => 'odl',
82     )
83   }
84 end
85
86 # Shared tests that specialize in testing Karaf feature installs
87 def karaf_feature_tests(options = {})
88   # Extract params
89   # NB: This default list should be the same as the one in opendaylight::params
90   # TODO: Remove this possible source of bugs^^
91   default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management'])
92   extra_features = options.fetch(:extra_features, [])
93
94   # The order of this list concat matters
95   features = default_features + extra_features
96   features_csv = features.join(',')
97
98   # Confirm properties of Karaf features config file
99   # NB: These hashes don't work with Ruby 1.8.7, but we
100   #   don't support 1.8.7 so that's okay. See issue #36.
101   it {
102     should contain_file('org.apache.karaf.features.cfg').with(
103       'ensure'      => 'file',
104       'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
105       'owner'   => 'odl',
106       'group'   => 'odl',
107     )
108   }
109   it {
110     should contain_file_line('featuresBoot').with(
111       'path'  => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
112       'line'  => "featuresBoot=#{features_csv}",
113       'match' => '^featuresBoot=.*$',
114     )
115   }
116 end
117
118 # Shared tests that specialize in testing ODL's REST port config
119 def odl_rest_port_tests(options = {})
120   # Extract params
121   # NB: This default value should be the same as one in opendaylight::params
122   # TODO: Remove this possible source of bugs^^
123   odl_rest_port = options.fetch(:odl_rest_port, 8080)
124
125   # Confirm properties of ODL REST port config file
126   # NB: These hashes don't work with Ruby 1.8.7, but we
127   #   don't support 1.8.7 so that's okay. See issue #36.
128   it {
129     should contain_file('jetty.xml').with(
130       'ensure'      => 'file',
131       'path'        => '/opt/opendaylight/etc/jetty.xml',
132       'owner'   => 'odl',
133       'group'   => 'odl',
134       'content'     => /Property name="jetty.port" default="#{odl_rest_port}"/
135     )
136   }
137 end
138
139 def log_level_tests(options = {})
140   # Extract params
141   # NB: This default value should be the same as one in opendaylight::params
142   # TODO: Remove this possible source of bugs^^
143   log_levels = options.fetch(:log_levels, {})
144
145   if log_levels.empty?
146     # Should contain log level config file
147     it {
148       should contain_file('org.ops4j.pax.logging.cfg').with(
149         'ensure'      => 'file',
150         'path'        => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
151         'owner'   => 'odl',
152         'group'   => 'odl',
153       )
154     }
155     # Should not contain custom log level config
156     it {
157       should_not contain_file('org.ops4j.pax.logging.cfg').with(
158         'ensure'      => 'file',
159         'path'        => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
160         'owner'   => 'odl',
161         'group'   => 'odl',
162         'content'     => /# Log level config added by puppet-opendaylight/
163       )
164     }
165   else
166     # Should contain log level config file
167     it {
168       should contain_file('org.ops4j.pax.logging.cfg').with(
169         'ensure'      => 'file',
170         'path'        => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
171         'owner'   => 'odl',
172         'group'   => 'odl',
173       )
174     }
175     # Should contain custom log level config
176     it {
177       should contain_file('org.ops4j.pax.logging.cfg').with(
178         'ensure'      => 'file',
179         'path'        => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
180         'owner'   => 'odl',
181         'group'   => 'odl',
182         'content'     => /# Log level config added by puppet-opendaylight/
183       )
184     }
185     # Verify each custom log level config entry
186     log_levels.each_pair do |logger, level|
187       it {
188         should contain_file('org.ops4j.pax.logging.cfg').with(
189           'ensure'      => 'file',
190           'path'        => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
191           'owner'   => 'odl',
192           'group'   => 'odl',
193           'content'     => /^log4j.logger.#{logger} = #{level}/
194         )
195       }
196     end
197   end
198 end
199
200 def enable_ha_tests(options = {})
201   # Extract params
202   enable_ha = options.fetch(:enable_ha, false)
203   ha_node_ips = options.fetch(:ha_node_ips, [])
204   ha_node_index = options.fetch(:ha_node_index, 0)
205   # HA_NODE_IPS size
206   ha_node_count = ha_node_ips.size
207
208   if (enable_ha) && (ha_node_count < 2)
209     # Check for HA_NODE_COUNT < 2
210     fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
211   end
212 end
213
214 def rpm_install_tests(options = {})
215   # Extract params
216   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-5-testing')
217   java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
218
219   # Default to CentOS 7 Yum repo URL
220
221   # Confirm presence of RPM-related resources
222   it { should contain_yumrepo(rpm_repo) }
223   it { should contain_package('opendaylight') }
224
225   # Confirm relationships between RPM-related resources
226   it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
227   it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
228
229   # Confirm properties of RPM-related resources
230   # NB: These hashes don't work with Ruby 1.8.7, but we
231   #   don't support 1.8.7 so that's okay. See issue #36.
232   it {
233     should contain_yumrepo(rpm_repo).with(
234       'enabled'     => '1',
235       'gpgcheck'    => '0',
236       'descr'       => 'OpenDaylight SDN Controller',
237       'baseurl'     => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
238     )
239   }
240   it {
241     should contain_package('opendaylight').with(
242       'ensure'   => 'present',
243     )
244   }
245
246   it {
247     should contain_file_line('java_options_systemd').with(
248       'ensure' => 'present',
249       'path' => '/usr/lib/systemd/system/opendaylight.service',
250       'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
251       'after' => 'ExecStart=/opt/opendaylight/bin/start',
252     )
253   }
254 end
255
256 def deb_install_tests(options = {})
257   # Extract params
258   deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/boron')
259
260   # Confirm the presence of Deb-related resources
261   it { should contain_apt__ppa(deb_repo) }
262   it { should contain_package('opendaylight') }
263
264   # Confirm relationships between Deb-related resources
265   it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
266   it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
267
268   # Confirm presence of Deb-related resources
269   it {
270     should contain_package('opendaylight').with(
271       'ensure'   => 'present',
272     )
273   }
274 end
275
276 # Shared tests for unsupported OSs
277 def unsupported_os_tests(options = {})
278   # Extract params
279   expected_msg = options.fetch(:expected_msg)
280   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-5-testing')
281
282   # Confirm that classes fail on unsupported OSs
283   it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
284   it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
285   it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
286   it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
287
288   # Confirm that other resources fail on unsupported OSs
289   it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
290   it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
291   it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
292   it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
293 end
294
295 # Shared tests that specialize in testing security group mode
296 def enable_sg_tests(sg_mode='stateful', os_release)
297   # Extract params
298   # NB: This default value should be the same as one in opendaylight::params
299   # TODO: Remove this possible source of bugs^^
300
301   it { should contain_file('/opt/opendaylight/etc/opendaylight') }
302   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
303   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
304   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
305
306   if os_release != '7.3' and sg_mode == 'stateful'
307     # Confirm sg_mode becomes learn
308     it {
309       should contain_file('netvirt-aclservice-config.xml').with(
310         'ensure'      => 'file',
311         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
312         'owner'   => 'odl',
313         'group'   => 'odl',
314         'content'     => /learn/
315       )
316     }
317   else
318     # Confirm other sg_mode is passed correctly
319     it {
320       should contain_file('netvirt-aclservice-config.xml').with(
321         'ensure'      => 'file',
322         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
323         'owner'   => 'odl',
324         'group'   => 'odl',
325         'content'     => /#{sg_mode}/
326       )
327     }
328   end
329 end
330
331 # Shared tests that specialize in testing VPP routing node config
332 def vpp_routing_node_tests(options = {})
333   # Extract params
334   # NB: This default list should be the same as the one in opendaylight::params
335   # TODO: Remove this possible source of bugs^^
336   routing_node = options.fetch(:routing_node, '')
337
338   if routing_node.empty?
339     it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.cfg') }
340     it { should_not contain_file_line('routing-node') }
341   else
342     # Confirm properties of Karaf config file
343     # NB: These hashes don't work with Ruby 1.8.7, but we
344     #   don't support 1.8.7 so that's okay. See issue #36.
345     it {
346       should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.cfg').with(
347         'ensure'      => 'file',
348         'path'        => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.cfg',
349         'owner'   => 'odl',
350         'group'   => 'odl',
351       )
352     }
353     it {
354       should contain_file_line('routing-node').with(
355         'path'  => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.cfg',
356         'line'  => "routing-node=#{routing_node}",
357         'match' => '^routing-node=.*$',
358       )
359     }
360   end
361 end