Merge "Bump Puppet version 4.x to 5.x"
[integration/packaging/puppet-opendaylight.git] / spec / spec_helper.rb
index a2dad80dcf48ed1f864c3bf46a4ae0bd3c45aea5..564be8d980bb9e3e148924b648c3cd2ab5f3f9bf 100644 (file)
@@ -3,34 +3,8 @@ require 'rspec-puppet-facts'
 include RspecPuppetFacts
 
 # Customize filters to ignore 3rd-party code
-# If the coverage report shows not-our-code results, add it here
+# If the rspec coverage report shows not-our-code results, add it here
 custom_filters = [
-  'Anchor[java::end]',
-  'Stage[setup]',
-  'Anchor[java::begin:]',
-  'Archive::Download[opendaylight.tar.gz]',
-  'Archive::Download[opendaylight-systemd.tar.gz]',
-  'Archive::Extract[opendaylight]',
-  'Archive::Extract[opendaylight-systemd]',
-  'Class[Java::Config]',
-  'Class[Java::Params]',
-  'Class[Stdlib::Stages]',
-  'Class[Stdlib]',
-  'Exec[download archive opendaylight.tar.gz and check sum]',
-  'Exec[download archive opendaylight-systemd.tar.gz and check sum]',
-  'Exec[opendaylight unpack]',
-  'Exec[opendaylight-systemd unpack]',
-  'Exec[rm-on-error-opendaylight.tar.gz]',
-  'Exec[rm-on-error-opendaylight-systemd.tar.gz]',
-  'Exec[reload_systemd_units]',
-  'Exec[update-java-alternatives]',
-  'Package[curl]',
-  'Stage[deploy]',
-  'Stage[deploy_app]',
-  'Stage[deploy_infra]',
-  'Stage[runtime]',
-  'Stage[setup_app]',
-  'Stage[setup_infra]',
 ]
 RSpec::Puppet::Coverage.filters.push(*custom_filters)
 
@@ -39,7 +13,11 @@ RSpec::Puppet::Coverage.filters.push(*custom_filters)
 #
 
 # Tests that are common to all possible configurations
-def generic_tests()
+def generic_tests(options = {})
+  java_opts = options.fetch(:java_opts, '')
+  odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
+  inactivity_probe = options.fetch(:inactivity_probe, :undef)
+
   # Confirm that module compiles
   it { should compile }
   it { should compile.with_all_deps }
@@ -49,6 +27,7 @@ def generic_tests()
   it { should contain_class('opendaylight::params') }
   it { should contain_class('opendaylight::install') }
   it { should contain_class('opendaylight::config') }
+  it { should contain_class('opendaylight::post_config') }
   it { should contain_class('opendaylight::service') }
 
   # Confirm relationships between classes
@@ -57,6 +36,8 @@ def generic_tests()
   it { should contain_class('opendaylight::config').that_notifies('Class[opendaylight::service]') }
   it { should contain_class('opendaylight::service').that_subscribes_to('Class[opendaylight::config]') }
   it { should contain_class('opendaylight::service').that_comes_before('Class[opendaylight]') }
+  it { should contain_class('opendaylight::post_config').that_requires('Class[opendaylight::service]') }
+  it { should contain_class('opendaylight::post_config').that_comes_before('Class[opendaylight]') }
   it { should contain_class('opendaylight').that_requires('Class[opendaylight::service]') }
 
   # Confirm presence of generic resources
@@ -82,26 +63,156 @@ def generic_tests()
       'group'   => 'odl',
     )
   }
+
+  it {
+    if odl_bind_ip =~ /.*:.*/
+        java_options = '-Djava.net.preferIPv6Addresses=true'
+    else
+        java_options = '-Djava.net.preferIPv4Stack=true'
+    end
+
+    should contain_file_line('Karaf Java Options').with(
+      'ensure' => 'present',
+      'path'   => '/opt/opendaylight/bin/karaf',
+      'line'   => "EXTRA_JAVA_OPTS=\"#{java_options}\"",
+      'match'  => '^EXTRA_JAVA_OPTS=.*$',
+      'after'  => '^PROGNAME=.*$'
+    )
+  }
+
+  it {
+    should contain_file('org.opendaylight.ovsdb.library.cfg').with(
+      'ensure'  => 'file',
+      'path'    => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+      'content' =>  /ovsdb-listener-ip = #{odl_bind_ip}/
+    )
+  }
+
+  it {
+    should contain_file('default-openflow-connection-config.xml').with(
+      'ensure'  => 'file',
+      'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+      'content' =>  /<address>#{odl_bind_ip}<\/address>/
+    )
+  }
+
+  unless inactivity_probe == :undef
+    it {
+      should contain_file('Configure inactivity probe timer').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+        'content' =>  /<controller-inactivity-probe>#{inactivity_probe}<\/controller-inactivity-probe>/
+      )
+    }
+  end
+
 end
 
 # Shared tests that specialize in testing log file size and rollover
-def log_file_settings(options = {})
+def log_settings(options = {})
   # Extraxt params. The dafault value should be same as in opendaylight::params
-  log_max_size = options.fetch(:log_max_size, '10GB')
-  log_max_rollover = options.fetch(:log_max_rollover, 2)
+  log_max_size = options.fetch(:log_max_size, '500MB')
+  log_max_rollover = options.fetch(:log_max_rollover, 4)
+  log_rollover_fileindex = options.fetch(:log_rollover_fileindex, 'min')
+  log_pattern = options.fetch(:log_pattern, '%d{ISO8601} | %-5p | %-16t | %-60c{6} | %m%n')
+  log_mechanism = options.fetch(:log_mechanism, 'file')
+  enable_paxosgi_logger = options.fetch(:enable_paxosgi_logger, false)
+
+  if log_mechanism == 'console'
+    it {
+      should contain_file_line('consoleappender').with(
+        'path'  => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'  => 'karaf.log.console=INFO',
+        'after' => 'log4j2.rootLogger.appenderRef.Console.filter.threshold.type = ThresholdFilter',
+        'match' => '^karaf.log.console.*$'
+      )
+    }
+    it {
+      should contain_file_line('direct').with(
+        'path'  => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'  => 'log4j2.appender.console.direct = true',
+        'after' => 'karaf.log.console=INFO',
+        'match' => '^log4j2.appender.console.direct.*$'
+      )
+    }
+  else
+
+    it {
+      should contain_file_line('logmaxsize').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'   => "log4j2.appender.rolling.policies.size.size = #{log_max_size}",
+        'match'  => '^log4j2.appender.rolling.policies.size.size.*$',
+      )
+    }
+    it {
+      should contain_file_line('rolloverstrategy').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'   => 'log4j2.appender.rolling.strategy.type = DefaultRolloverStrategy'
+      )
+    }
+    it {
+      should contain_file_line('logmaxrollover').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'   => "log4j2.appender.rolling.strategy.max = #{log_max_rollover}",
+        'match'  => '^log4j2.appender.rolling.strategy.max.*$',
+      )
+    }
+    it {
+      should contain_file_line('logrolloverfileindex').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+        'line'   => "log4j2.appender.rolling.strategy.fileIndex = #{log_rollover_fileindex}",
+        'match'  => '^log4j2.appender.rolling.strategy.fileIndex.*$',
+      )
+    }
+  end
+  it {
+    should contain_file_line('logpattern').with(
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "log4j2.pattern = #{log_pattern}",
+      'match'  => '^log4j2.pattern.*$',
+    )
+  }
+  if enable_paxosgi_logger == true
+      presence = 'present'
+  else
+      presence = 'absent'
+  end
 
   it {
-    should contain_file_line('logmaxsize').with(
+    should contain_file_line('paxosgiappenderref').with(
+      'ensure' => presence,
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "log4j2.rootLogger.appenderRef.PaxOsgi.ref = PaxOsgi",
+    )
+  }
+  it {
+    should contain_file_line('paxosgisection').with(
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "# OSGi appender",
+    )
+  }
+  it {
+    should contain_file_line('paxosgitype').with(
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "log4j2.appender.osgi.type = PaxOsgi",
+    )
+  }
+  it {
+    should contain_file_line('paxosginame').with(
       'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
-      'line'   => "log4j.appender.out.maxFileSize=#{log_max_size}",
-      'match'  => '^log4j.appender.out.maxFileSize.*$',
+      'line'   => "log4j2.appender.osgi.name = PaxOsgi",
     )
   }
   it {
-    should contain_file_line('logmaxrollover').with(
+    should contain_file_line('paxosgifilter').with(
       'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
-      'line'   => "log4j.appender.out.maxBackupIndex=#{log_max_rollover}",
-      'match'  => '^log4j.appender.out.maxBackupIndex.*$',
+      'line'   => "log4j2.appender.osgi.filter = *",
     )
   }
 end
@@ -110,8 +221,7 @@ end
 def karaf_feature_tests(options = {})
   # Extract params
   # NB: This default list should be the same as the one in opendaylight::params
-  # TODO: Remove this possible source of bugs^^
-  default_features = options.fetch(:default_features, ['config', 'standard', 'region', 'package', 'kar', 'ssh', 'management'])
+  default_features = options.fetch(:default_features, ['standard', 'wrap', 'ssh'])
   extra_features = options.fetch(:extra_features, [])
 
   # The order of this list concat matters
@@ -142,19 +252,44 @@ end
 def odl_rest_port_tests(options = {})
   # Extract params
   # NB: This default value should be the same as one in opendaylight::params
-  # TODO: Remove this possible source of bugs^^
-  odl_rest_port = options.fetch(:odl_rest_port, 8080)
-
+  odl_rest_port = options.fetch(:odl_rest_port, 8181)
+  odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
   # Confirm properties of ODL REST port config file
   # NB: These hashes don't work with Ruby 1.8.7, but we
   #   don't support 1.8.7 so that's okay. See issue #36.
   it {
-    should contain_file('jetty.xml').with(
-      'ensure'      => 'file',
-      'path'        => '/opt/opendaylight/etc/jetty.xml',
-      'owner'   => 'odl',
-      'group'   => 'odl',
-      'content'     => /Property name="jetty.port" default="#{odl_rest_port}"/
+    should contain_augeas('ODL REST Port')
+  }
+
+  if not odl_bind_ip.eql? '0.0.0.0'
+    it {
+      should contain_augeas('ODL REST IP')
+      should contain_file_line('set pax bind IP').with(
+        'ensure'  => 'present',
+        'path'    => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'    => "org.ops4j.pax.web.listening.addresses = #{odl_bind_ip}",
+        'require' => 'File[org.ops4j.pax.web.cfg]'
+      )
+      should contain_file_line('set karaf IP').with(
+        'ensure' => 'present',
+        'path'   => '/opt/opendaylight/etc/org.apache.karaf.shell.cfg',
+        'line'   => "sshHost = #{odl_bind_ip}",
+        'match'  => '^sshHost\s*=.*$',
+      )
+    }
+  else
+    it {
+      should_not contain_augeas('ODL REST IP')
+    }
+  end
+
+  it {
+    should contain_file_line('set pax bind port').with(
+        'ensure'  => 'present',
+        'path'    => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'    => "org.osgi.service.http.port = #{odl_rest_port}",
+        'match'   => '^#?org.osgi.service.http.port\s.*$',
+        'require' => 'File[org.ops4j.pax.web.cfg]'
     )
   }
 end
@@ -162,22 +297,32 @@ end
 def log_level_tests(options = {})
   # Extract params
   # NB: This default value should be the same as one in opendaylight::params
-  # TODO: Remove this possible source of bugs^^
   log_levels = options.fetch(:log_levels, {})
 
   if log_levels.empty?
     # Should contain log level config file
     it {
-      should_not contain_file_line('logger-org.opendaylight.ovsdb')
+      should_not contain_file_line('logger-org.opendaylight.ovsdb-level')
+    }
+    it {
+      should_not contain_file_line('logger-org.opendaylight.ovsdb-name')
     }
   else
     # Verify each custom log level config entry
     log_levels.each_pair do |logger, level|
+      underscored_version = "#{logger}".gsub('.', '_')
       it {
-        should contain_file_line("logger-#{logger}").with(
+        should contain_file_line("logger-#{logger}-level").with(
+          'ensure' => 'present',
+          'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+          'line' => "log4j2.logger.#{underscored_version}.level = #{level}",
+          'match'  => "log4j2.logger.#{underscored_version}.level = .*$"
+        )
+        should contain_file_line("logger-#{logger}-name").with(
           'ensure' => 'present',
           'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
-          'line' => "log4j.logger.#{logger}=#{level}",
+          'line' => "log4j2.logger.#{underscored_version}.name = #{logger}",
+          'match'  => "log4j2.logger.#{underscored_version}.name = .*$"
         )
       }
     end
@@ -246,28 +391,28 @@ end
 
 def rpm_install_tests(options = {})
   # Extract params
-  rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
-  java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
+  rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel')
+
 
   # Default to CentOS 7 Yum repo URL
 
   # Confirm presence of RPM-related resources
-  it { should contain_yumrepo(rpm_repo) }
+  it { should contain_yumrepo('opendaylight') }
   it { should contain_package('opendaylight') }
 
   # Confirm relationships between RPM-related resources
-  it { should contain_package('opendaylight').that_requires("Yumrepo[#{rpm_repo}]") }
-  it { should contain_yumrepo(rpm_repo).that_comes_before('Package[opendaylight]') }
+  it { should contain_package('opendaylight').that_requires('Yumrepo[opendaylight]') }
+  it { should contain_yumrepo('opendaylight').that_comes_before('Package[opendaylight]') }
 
   # Confirm properties of RPM-related resources
   # NB: These hashes don't work with Ruby 1.8.7, but we
   #   don't support 1.8.7 so that's okay. See issue #36.
   it {
-    should contain_yumrepo(rpm_repo).with(
+    should contain_yumrepo('opendaylight').with(
       'enabled'     => '1',
       'gpgcheck'    => '0',
       'descr'       => 'OpenDaylight SDN Controller',
-      'baseurl'     => "http://cbs.centos.org/repos/nfv7-#{rpm_repo}/$basearch/os/",
+      'baseurl'     => "#{rpm_repo}",
     )
   }
   it {
@@ -275,20 +420,11 @@ def rpm_install_tests(options = {})
       'ensure'   => 'present',
     )
   }
-
-  it {
-    should contain_file_line('java_options_systemd').with(
-      'ensure' => 'present',
-      'path' => '/usr/lib/systemd/system/opendaylight.service',
-      'line' => "Environment=_JAVA_OPTIONS=\'#{java_opts}\'",
-      'after' => 'ExecStart=/opt/opendaylight/bin/start',
-    )
-  }
 end
 
 def deb_install_tests(options = {})
   # Extract params
-  deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/carbon')
+  deb_repo = options.fetch(:deb_repo, 'ppa:odl-team/nitrogen')
 
   # Confirm the presence of Deb-related resources
   it { should contain_apt__ppa(deb_repo) }
@@ -310,7 +446,7 @@ end
 def unsupported_os_tests(options = {})
   # Extract params
   expected_msg = options.fetch(:expected_msg)
-  rpm_repo = options.fetch(:rpm_repo, 'opendaylight-6-testing')
+  rpm_repo = options.fetch(:rpm_repo, 'https://nexus.opendaylight.org/content/repositories/opendaylight-neon-epel-7-$basearch-devel')
 
   # Confirm that classes fail on unsupported OSs
   it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
@@ -319,43 +455,79 @@ def unsupported_os_tests(options = {})
   it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
 
   # Confirm that other resources fail on unsupported OSs
-  it { expect { should contain_yumrepo(rpm_repo) }.to raise_error(Puppet::Error, /#{expected_msg}/) }
+  it { expect { should contain_yumrepo('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
   it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
   it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
   it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
 end
 
-# Shared tests that specialize in testing security group mode
-def enable_sg_tests(sg_mode='stateful', os_release)
-  # Extract params
-  # NB: This default value should be the same as one in opendaylight::params
-  # TODO: Remove this possible source of bugs^^
+# Shared tests that specialize in testing SNAT mechanism
+def snat_mechanism_tests(snat_mechanism='controller')
+  it { should contain_file('/opt/opendaylight/etc/opendaylight') }
+  it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
+  it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
+  it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
+
+  # Confirm snat_mechanism
+  it {
+    should contain_file('netvirt-natservice-config.xml').with(
+      'ensure'      => 'file',
+      'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-natservice-config.xml',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+      'content'     =>  /<nat-mode>#{snat_mechanism}<\/nat-mode>/
+      )
+    }
+end
+
+# Shared tests that specialize in testing SFC Config
+def sfc_tests(options = {})
+  extra_features = options.fetch(:extra_features, [])
+
+  if extra_features.include? 'odl-netvirt-sfc'
+    sfc_enabled = true
+  else
+    sfc_enabled = false
+  end
 
   it { should contain_file('/opt/opendaylight/etc/opendaylight') }
   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore')}
   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial')}
   it { should contain_file('/opt/opendaylight/etc/opendaylight/datastore/initial/config')}
 
-  if os_release != '7.3' and sg_mode == 'stateful'
-    # Confirm sg_mode becomes learn
+  it {
+    should contain_file('genius-itm-config.xml').with(
+      'ensure'  => 'file',
+      'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+      'content' => /<gpe-extension-enabled>#{sfc_enabled}<\/gpe-extension-enabled>/
+      )
+    }
+end
+
+# Shared tests that specialize in testing DSCP marking config
+def dscp_tests(options = {})
+  inherit_dscp_marking = options.fetch(:inherit_dscp_marking, false)
+
+  if inherit_dscp_marking
     it {
-      should contain_file('netvirt-aclservice-config.xml').with(
-        'ensure'      => 'file',
-        'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
+      should contain_file('genius-itm-config.xml').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
         'owner'   => 'odl',
         'group'   => 'odl',
-        'content'     => /learn/
+        'content' => /<default-tunnel-tos>inherit<\/default-tunnel-tos>/
       )
     }
   else
-    # Confirm other sg_mode is passed correctly
     it {
-      should contain_file('netvirt-aclservice-config.xml').with(
-        'ensure'      => 'file',
-        'path'        => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml',
+      should contain_file('genius-itm-config.xml').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/genius-itm-config.xml',
         'owner'   => 'odl',
         'group'   => 'odl',
-        'content'     => /#{sg_mode}/
+        'content' => /<default-tunnel-tos>0<\/default-tunnel-tos>/
       )
     }
   end
@@ -365,7 +537,6 @@ end
 def vpp_routing_node_tests(options = {})
   # Extract params
   # NB: This default list should be the same as the one in opendaylight::params
-  # TODO: Remove this possible source of bugs^^
   routing_node = options.fetch(:routing_node, '')
 
   if routing_node.empty?
@@ -402,3 +573,155 @@ def username_password_tests(username, password)
     )
   }
 end
+
+# ODL websocket address tests
+def odl_websocket_address_tests(options = {})
+  # Extract params
+  # NB: This default value should be the same as one in opendaylight::params
+  odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
+  # Confirm properties of ODL REST port config file
+  # NB: These hashes don't work with Ruby 1.8.7, but we
+  #   don't support 1.8.7 so that's okay. See issue #36.
+
+  if not odl_bind_ip.eql? '0.0.0.0'
+    it {
+      should contain_file('/opt/opendaylight/etc/org.opendaylight.restconf.cfg').with(
+        'ensure'      => 'file',
+        'path'        => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+      )
+    }
+    it {
+        should contain_file_line('websocket-address').with(
+          'path'    => '/opt/opendaylight/etc/org.opendaylight.restconf.cfg',
+          'line'    => "websocket-address=#{odl_bind_ip}",
+          'match'   => '^websocket-address=.*$',
+      )
+    }
+  else
+    it {
+      should_not contain_file_line('websocket-address')
+    }
+  end
+end
+
+def odl_tls_tests(options = {})
+  enable_tls = options.fetch(:enable_tls, false)
+  tls_keystore_password = options.fetch(:tls_keystore_password, nil)
+  tls_trusted_certs = options.fetch(:tls_trusted_certs, [])
+  tls_keystore_password = options.fetch(:tls_keystore_password, nil)
+  tls_key_file = options.fetch(:tls_key_file, nil)
+  tls_cert_file = options.fetch(:tls_cert_file, nil)
+  tls_ca_cert_file = options.fetch(:tls_ca_cert_file, nil)
+  odl_rest_port = options.fetch(:odl_rest_port, 8181)
+
+  if enable_tls
+    if tls_keystore_password.nil?
+      it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) }
+      return
+    end
+
+    if tls_key_file or tls_cert_file
+      if tls_key_file and tls_cert_file
+        it {
+          should contain_odl_keystore('controller')
+        }
+      else
+        it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::PreformattedError) }
+      end
+    end
+    it {
+      should contain_augeas('Remove HTTP ODL REST Port')
+      should contain_augeas('ODL SSL REST Port')
+      should contain_file_line('set pax TLS port').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => "org.osgi.service.http.port.secure = #{odl_rest_port}",
+        'match'  => '^#?org.osgi.service.http.port.secure.*$',
+      )
+      should contain_file_line('set pax TLS keystore location').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => 'org.ops4j.pax.web.ssl.keystore = configuration/ssl/ctl.jks',
+        'match'  => '^#?org.ops4j.pax.web.ssl.keystore.*$',
+      )
+      should contain_file_line('set pax TLS keystore integrity password').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => "org.ops4j.pax.web.ssl.password = #{tls_keystore_password}",
+        'match'  => '^#?org.ops4j.pax.web.ssl.password.*$',
+      )
+      should contain_file_line('set pax TLS keystore password').with(
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => "org.ops4j.pax.web.ssl.keypassword = #{tls_keystore_password}",
+        'match'  => '^#?org.ops4j.pax.web.ssl.keypassword.*$',
+      )
+      should contain_file('aaa-cert-config.xml').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/aaa-cert-config.xml',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+      )
+      should contain_file('org.opendaylight.ovsdb.library.cfg').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+        'content' =>  /use-ssl = true/
+      )
+      should contain_file('/opt/opendaylight/configuration/ssl').with(
+        'ensure' => 'directory',
+        'path'   => '/opt/opendaylight/configuration/ssl',
+        'owner'  => 'odl',
+        'group'  => 'odl',
+        'mode'   => '0755'
+      )
+      should contain_file_line('enable pax TLS').with(
+        'ensure' => 'present',
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => 'org.osgi.service.http.secure.enabled = true',
+        'match'  => '^#?org.osgi.service.http.secure.enabled.*$',
+      )
+      should contain_file_line('disable pax HTTP').with(
+        'ensure' => 'present',
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'   => 'org.osgi.service.http.enabled = false',
+        'match'  => '^#?org.osgi.service.http.enabled.*$',
+      )
+      should contain_file('org.ops4j.pax.web.cfg').with(
+        'ensure' => 'file',
+        'path'   => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'owner'  => 'odl',
+        'group'  => 'odl',
+      )
+      should contain_file('default-openflow-connection-config.xml').with(
+        'ensure'  => 'file',
+        'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/default-openflow-connection-config.xml',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+        'content' =>  /<transport-protocol>TLS<\/transport-protocol>/
+      )
+    }
+  end
+end
+
+def stats_polling_enablement_tests(options = {})
+  # Extract params
+  # NB: This default value should be the same as one in opendaylight::params
+  stats_polling_enabled = options.fetch(:stats_polling_enabled, false)
+  # Confirm properties of ODL REST port config file
+  # NB: These hashes don't work with Ruby 1.8.7, but we
+  #   don't support 1.8.7 so that's okay. See issue #36.
+  it {
+    should contain_file('openflowplugin.cfg').with(
+      'ensure' => 'file',
+      'path'   => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg',
+      'owner'  => 'odl',
+      'group'  => 'odl',
+    )
+    should contain_file_line('stats-polling').with(
+      'ensure' => 'present',
+      'path'   => '/opt/opendaylight/etc/org.opendaylight.openflowplugin.cfg',
+      'line'   => "is-statistics-polling-on=#{stats_polling_enabled}",
+      'match'  => '^is-statistics-polling-on=.*$',
+    )
+  }
+end