Fix bind IP config for REST
[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   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.
125   it {
126     should contain_augeas('ODL REST Port')
127   }
128
129   if not odl_bind_ip.eql? '0.0.0.0'
130     it {
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}",
135       )
136     }
137   else
138     it {
139       should_not contain_augeas('ODL REST IP')
140     }
141   end
142 end
143
144 def log_level_tests(options = {})
145   # Extract params
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, {})
149
150   if log_levels.empty?
151     # Should contain log level config file
152     it {
153       should_not contain_file_line('logger-org.opendaylight.ovsdb')
154     }
155   else
156     # Verify each custom log level config entry
157     log_levels.each_pair do |logger, level|
158       it {
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}",
163         )
164       }
165     end
166   end
167 end
168
169 def enable_ha_tests(options = {})
170   # Extract params
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 })
175   # HA_NODE_IPS size
176   ha_node_count = ha_node_ips.size
177
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")
181   end
182
183   if enable_ha
184     ha_node_index = ha_node_ips.index(odl_bind_ip)
185     it {
186       should contain_file('akka.conf').with(
187         'path'    => '/opt/opendaylight/configuration/initial/akka.conf',
188         'ensure'  => 'file',
189         'owner'   => 'odl',
190         'group'   => 'odl',
191         'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
192       )
193     }
194
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',
198         'ensure'  => 'file',
199         'owner'   => 'odl',
200         'group'   => 'odl',
201         'content' => /name = "#{mod}"/
202       )}
203       if mod == 'default'
204         it { should contain_file('modules.conf').with(
205           'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
206           'ensure'  => 'file',
207           'owner'   => 'odl',
208           'group'   => 'odl'
209         )}
210       else
211         it { should contain_file('modules.conf').with(
212           'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
213           'ensure'  => 'file',
214           'owner'   => 'odl',
215           'group'   => 'odl',
216           'content' => /name = "#{mod}"/,
217         )}
218       end
219     end
220   else
221     it {
222       should_not contain_file('akka.conf')
223       should_not contain_file('module-shards.conf')
224       should_not contain_file('modules.conf')
225       }
226   end
227 end
228
229 def rpm_install_tests(options = {})
230   # Extract params
231   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
232   java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
233
234   # Default to CentOS 7 Yum repo URL
235
236   # Confirm presence of RPM-related resources
237   it { should contain_yumrepo(rpm_repo) }
238   it { should contain_package('opendaylight') }
239
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]') }
243
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.
247   it {
248     should contain_yumrepo(rpm_repo).with(
249       'enabled'     => '1',
250       'gpgcheck'    => '0',
251       'descr'       => 'OpenDaylight SDN Controller',
252       'baseurl'     => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
253     )
254   }
255   it {
256     should contain_package('opendaylight').with(
257       'ensure'   => 'present',
258     )
259   }
260
261   it {
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',
267     )
268   }
269 end
270
271 def deb_install_tests(options = {})
272   # Extract params
273   deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
274
275   # Confirm the presence of Deb-related resources
276   it { should contain_apt__ppa(deb_repo) }
277   it { should contain_package('opendaylight') }
278
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]') }
282
283   # Confirm presence of Deb-related resources
284   it {
285     should contain_package('opendaylight').with(
286       'ensure'   => 'present',
287     )
288   }
289 end
290
291 # Shared tests for unsupported OSs
292 def unsupported_os_tests(options = {})
293   # Extract params
294   expected_msg = options.fetch(:expected_msg)
295   rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
296
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}/) }
302
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}/) }
308 end
309
310 # Shared tests that specialize in testing security group mode
311 def enable_sg_tests(sg_mode='stateful', os_release)
312   # Extract params
313   # NB: This default value should be the same as one in opendaylight::params
314   # TODO: Remove this possible source of bugs^^
315
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')}
320
321   if os_release != '7.3' and sg_mode == 'stateful'
322     # Confirm sg_mode becomes learn
323     it {
324       should contain_file('netvirt-aclservice-config.xml').with(
325         'ensure'      => 'file',
326         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
327         'owner'   => 'odl',
328         'group'   => 'odl',
329         'content'     => /learn/
330       )
331     }
332   else
333     # Confirm other sg_mode is passed correctly
334     it {
335       should contain_file('netvirt-aclservice-config.xml').with(
336         'ensure'      => 'file',
337         'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
338         'owner'   => 'odl',
339         'group'   => 'odl',
340         'content'     => /#{sg_mode}/
341       )
342     }
343   end
344 end
345
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')}
352
353   # Confirm snat_mechanism
354   it {
355     should contain_file('netvirt-natservice-config.xml').with(
356       'ensure'      => 'file',
357       'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
358       'owner'   => 'odl',
359       'group'   => 'odl',
360       'content'     =>  /<nat-mode>#{snat_mechanism}<\/nat-mode>/
361       )
362     }
363 end
364
365 # Shared tests that specialize in testing SFC Config
366 def sfc_tests()
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')}
371
372   it {
373     should contain_file('netvirt-elanmanager-config.xml').with(
374       'ensure'  => 'file',
375       'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
376       'owner'   => 'odl',
377       'group'   => 'odl',
378       'source'  => 'puppet:///modules/opendaylight/netvirt-elanmanager-config.xml'
379       )
380     should contain_file('genius-itm-config.xml').with(
381       'ensure'  => 'file',
382       'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
383       'owner'   => 'odl',
384       'group'   => 'odl',
385       'source'  => 'puppet:///modules/opendaylight/genius-itm-config.xml'
386       )
387     }
388 end
389
390 # Shared tests that specialize in testing VPP routing node config
391 def vpp_routing_node_tests(options = {})
392   # Extract params
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, '')
396
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') }
400   else
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.
404     it {
405       should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
406         'ensure'      => 'file',
407         'path'        => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
408         'owner'   => 'odl',
409         'group'   => 'odl',
410       )
411     }
412     it {
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=.*$',
417       )
418     }
419   end
420 end
421
422 # ODL username/password tests
423 def username_password_tests(username, password)
424
425   it {
426     should contain_odl_user(username).with(
427       :password => password
428     )
429   }
430 end