Allow full customization of ODL RPM repo
[integration/packaging/puppet-opendaylight.git] / spec / spec_helper.rb
index d1e9d96f1b1b2121b5a54a36210b020b2b13dfd5..f0355eb3bf74e2d19f521e5d6c511b193ed98889 100644 (file)
@@ -1,7 +1,19 @@
 require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+include RspecPuppetFacts
+
+# Customize filters to ignore 3rd-party code
+# If the rspec coverage report shows not-our-code results, add it here
+custom_filters = [
+]
+RSpec::Puppet::Coverage.filters.push(*custom_filters)
+
+#
+# NB: This is a library of helper fns used by the rspec-puppet tests
+#
 
 # Tests that are common to all possible configurations
-def generic_tests(yum_repo)
+def generic_tests()
   # Confirm that module compiles
   it { should compile }
   it { should compile.with_all_deps }
@@ -14,14 +26,14 @@ def generic_tests(yum_repo)
   it { should contain_class('opendaylight::service') }
 
   # Confirm relationships between classes
-  it { should contain_class('opendaylight::install').that_comes_before('opendaylight::config') }
-  it { should contain_class('opendaylight::config').that_requires('opendaylight::install') }
-  it { should contain_class('opendaylight::config').that_notifies('opendaylight::service') }
-  it { should contain_class('opendaylight::service').that_subscribes_to('opendaylight::config') }
-  it { should contain_class('opendaylight::service').that_comes_before('opendaylight') }
-  it { should contain_class('opendaylight').that_requires('opendaylight::service') }
-
-  # Confirm presense of generic resources
+  it { should contain_class('opendaylight::install').that_comes_before('Class[opendaylight::config]') }
+  it { should contain_class('opendaylight::config').that_requires('Class[opendaylight::install]') }
+  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').that_requires('Class[opendaylight::service]') }
+
+  # Confirm presence of generic resources
   it { should contain_service('opendaylight') }
   it { should contain_file('org.apache.karaf.features.cfg') }
 
@@ -39,143 +51,344 @@ def generic_tests(yum_repo)
   it {
     should contain_file('org.apache.karaf.features.cfg').with(
       'ensure'      => 'file',
-      'path'        => '/opt/opendaylight-0.2.2/etc/org.apache.karaf.features.cfg',
+      'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+    )
+  }
+end
+
+# Shared tests that specialize in testing log file size and rollover
+def log_file_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)
+
+  it {
+    should contain_file_line('logmaxsize').with(
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "log4j.appender.out.maxFileSize=#{log_max_size}",
+      'match'  => '^log4j.appender.out.maxFileSize.*$',
+    )
+  }
+  it {
+    should contain_file_line('logmaxrollover').with(
+      'path'   => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+      'line'   => "log4j.appender.out.maxBackupIndex=#{log_max_rollover}",
+      'match'  => '^log4j.appender.out.maxBackupIndex.*$',
     )
   }
 end
 
 # Shared tests that specialize in testing Karaf feature installs
-def karaf_feature_tests(features)
-  # Confirm properties of other resources
+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, ['standard', 'wrap', 'ssh'])
+  extra_features = options.fetch(:extra_features, [])
+
+  # The order of this list concat matters
+  features = default_features + extra_features
+  features_csv = features.join(',')
+
+  # Confirm properties of Karaf features 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('org.apache.karaf.features.cfg').with(
       'ensure'      => 'file',
-      'path'        => '/opt/opendaylight-0.2.2/etc/org.apache.karaf.features.cfg',
-      'content'     => /^featuresBoot=#{features.join(",")}/
+      'path'        => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+    )
+  }
+  it {
+    should contain_file_line('featuresBoot').with(
+      'path'  => '/opt/opendaylight/etc/org.apache.karaf.features.cfg',
+      'line'  => "featuresBoot=#{features_csv}",
+      'match' => '^featuresBoot=.*$',
     )
   }
 end
 
-def install_method_tests(method, yum_repo, tarball_url='', unitfile_url='')
-  case method
-  when 'rpm'
-    # Confirm presense of RPM-related resources
-    it { should contain_yumrepo('opendaylight') }
-    it { should contain_package('opendaylight') }
-
-    # Confirm relationships between RPM-related resources
-    it { should contain_package('opendaylight').that_requires('Yumrepo[opendaylight]') }
-    it { should contain_yumrepo('opendaylight').that_comes_before('Package[opendaylight]') }
+# Shared tests that specialize in testing ODL's REST port config
+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_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_augeas('ODL REST Port')
+  }
 
-    # 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.
+  if not odl_bind_ip.eql? '0.0.0.0'
     it {
-      should contain_yumrepo('opendaylight').with(
-        'enabled'     => '1',
-        'gpgcheck'    => '0',
-        'descr'       => 'OpenDaylight SDN controller',
-        'baseurl'     => yum_repo,
+      should contain_augeas('ODL REST IP')
+      should contain_file_line('org.ops4j.pax.web.cfg').with(
+        'path'  => '/opt/opendaylight/etc/org.ops4j.pax.web.cfg',
+        'line'  => "org.ops4j.pax.web.listening.addresses = #{odl_bind_ip}",
       )
     }
+  else
     it {
-      should contain_package('opendaylight').with(
-        'ensure'   => 'present',
-      )
+      should_not contain_augeas('ODL REST IP')
     }
-  when 'tarball'
-    if tarball_url == ''
-      fail('Expected tarball_url param')
-    end
+  end
+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 unitfile_url == ''
-      fail('Expected unitfile_url param')
+  if log_levels.empty?
+    # Should contain log level config file
+    it {
+      should_not contain_file_line('logger-org.opendaylight.ovsdb')
+    }
+  else
+    # Verify each custom log level config entry
+    log_levels.each_pair do |logger, level|
+      it {
+        should contain_file_line("logger-#{logger}").with(
+          'ensure' => 'present',
+          'path' => '/opt/opendaylight/etc/org.ops4j.pax.logging.cfg',
+          'line' => "log4j.logger.#{logger}=#{level}",
+        )
+      }
     end
+  end
+end
 
-    # Confirm presense of tarball-related resources
-    it { should contain_archive('opendaylight-0.2.2') }
-    it { should contain_archive('opendaylight-systemd') }
-    it { should contain_class('java') }
-    it { should contain_file('/opt/opendaylight-0.2.2/') }
-    it { should contain_file('/usr/lib/systemd/system/opendaylight.service') }
-
-    # Confirm relationships between tarball-related resources
-    it { should contain_archive('opendaylight-0.2.2').that_comes_before('File[/opt/opendaylight-0.2.2/]') }
-    it { should contain_archive('opendaylight-0.2.2').that_comes_before('User[odl]') }
-    it { should contain_archive('opendaylight-systemd').that_comes_before('File[/usr/lib/systemd/system/opendaylight.service]') }
-    it { should contain_file('/opt/opendaylight-0.2.2/').that_requires('Archive[opendaylight-0.2.2]') }
-    it { should contain_file('/opt/opendaylight-0.2.2/').that_requires('Group[odl]') }
-    it { should contain_file('/opt/opendaylight-0.2.2/').that_requires('User[odl]') }
-    it { should contain_file('/usr/lib/systemd/system/opendaylight.service').that_requires('Archive[opendaylight-systemd]') }
-
-    # Confirm properties of tarball-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.
+def enable_ha_tests(options = {})
+  # Extract params
+  enable_ha = options.fetch(:enable_ha, false)
+  odl_bind_ip = options.fetch(:odl_bind_ip, '0.0.0.0')
+  ha_node_ips = options.fetch(:ha_node_ips, [])
+  ha_db_modules = options.fetch(:ha_db_modules, { 'default' => false })
+  # HA_NODE_IPS size
+  ha_node_count = ha_node_ips.size
+
+  if (enable_ha) && (ha_node_count < 2)
+    # Check for HA_NODE_COUNT < 2
+    fail("Number of HA nodes less than 2: #{ha_node_count} and HA Enabled")
+  end
+
+  if enable_ha
+    ha_node_index = ha_node_ips.index(odl_bind_ip)
     it {
-      should contain_archive('opendaylight-0.2.2').with(
-        'ensure'           => 'present',
-        'url'              => tarball_url,
-        'target'           => '/opt/opendaylight-0.2.2',
-        'checksum'         => false,
-        'strip_components' => 1,
-        'timeout'          => 600,
+      should contain_file('akka.conf').with(
+        'path'    => '/opt/opendaylight/configuration/initial/akka.conf',
+        'ensure'  => 'file',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+        'content' => /roles\s*=\s*\["member-#{ha_node_index}"\]/
       )
     }
+
+    ha_db_modules.each do |mod, urn|
+      it { should contain_file('module-shards.conf').with(
+        'path'    => '/opt/opendaylight/configuration/initial/module-shards.conf',
+        'ensure'  => 'file',
+        'owner'   => 'odl',
+        'group'   => 'odl',
+        'content' => /name = "#{mod}"/
+      )}
+      if mod == 'default'
+        it { should contain_file('modules.conf').with(
+          'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
+          'ensure'  => 'file',
+          'owner'   => 'odl',
+          'group'   => 'odl'
+        )}
+      else
+        it { should contain_file('modules.conf').with(
+          'path'    => '/opt/opendaylight/configuration/initial/modules.conf',
+          'ensure'  => 'file',
+          'owner'   => 'odl',
+          'group'   => 'odl',
+          'content' => /name = "#{mod}"/,
+        )}
+      end
+    end
+  else
     it {
-      should contain_archive('opendaylight-systemd').with(
-        'ensure'           => 'present',
-        'url'              => unitfile_url,
-        'target'           => '/usr/lib/systemd/system/',
-        'root_dir'         => 'opendaylight.service',
-        'checksum'         => false,
-        'strip_components' => 1,
-        'follow_redirects' => true,
+      should_not contain_file('akka.conf')
+      should_not contain_file('module-shards.conf')
+      should_not contain_file('modules.conf')
+      }
+  end
+end
+
+def rpm_install_tests(options = {})
+  # Extract params
+  rpm_repo = options.fetch(:rpm_repo, 'http://cbs.centos.org/repos/nfv7-opendaylight-8-testing/$basearch/os/')
+  java_opts = options.fetch(:java_opts, '-Djava.net.preferIPv4Stack=true')
+
+  # Default to CentOS 7 Yum repo URL
+
+  # Confirm presence of RPM-related resources
+  it { should contain_yumrepo('opendaylight') }
+  it { should contain_package('opendaylight') }
+
+  # Confirm relationships between RPM-related resources
+  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('opendaylight').with(
+      'enabled'     => '1',
+      'gpgcheck'    => '0',
+      'descr'       => 'OpenDaylight SDN Controller',
+      'baseurl'     => "#{rpm_repo}",
+    )
+  }
+  it {
+    should contain_package('opendaylight').with(
+      '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')
+
+  # Confirm the presence of Deb-related resources
+  it { should contain_apt__ppa(deb_repo) }
+  it { should contain_package('opendaylight') }
+
+  # Confirm relationships between Deb-related resources
+  it { should contain_package('opendaylight').that_requires("Apt::Ppa[#{deb_repo}]") }
+  it { should contain_apt__ppa(deb_repo).that_comes_before('Package[opendaylight]') }
+
+  # Confirm presence of Deb-related resources
+  it {
+    should contain_package('opendaylight').with(
+      'ensure'   => 'present',
+    )
+  }
+end
+
+# Shared tests for unsupported OSs
+def unsupported_os_tests(options = {})
+  # Extract params
+  expected_msg = options.fetch(:expected_msg)
+  rpm_repo = options.fetch(:rpm_repo, 'http://cbs.centos.org/repos/nfv7-opendaylight-8-testing/$basearch/os/')
+
+  # Confirm that classes fail on unsupported OSs
+  it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
+  it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
+  it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_msg}/) }
+  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('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 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>/
       )
     }
-    it {
-      should contain_package('java').with(
-        'name' => 'java-1.7.0-openjdk',
+end
+
+# Shared tests that specialize in testing SFC Config
+def sfc_tests()
+  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')}
+
+  it {
+    should contain_file('netvirt-elanmanager-config.xml').with(
+      'ensure'  => 'file',
+      'path'    => '/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-elanmanager-config.xml',
+      'owner'   => 'odl',
+      'group'   => 'odl',
+      'source'  => 'puppet:///modules/opendaylight/netvirt-elanmanager-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',
+      'source'  => 'puppet:///modules/opendaylight/genius-itm-config.xml'
       )
     }
+end
+
+# Shared tests that specialize in testing VPP routing node config
+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?
+    it { should_not contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg') }
+    it { should_not contain_file_line('routing-node') }
+  else
+    # Confirm properties of Karaf 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('/opt/opendaylight-0.2.2/').with(
-        'ensure'  => 'directory',
-        'recurse' => true,
+      should contain_file('org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg').with(
+        'ensure'      => 'file',
+        'path'        => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
         'owner'   => 'odl',
         'group'   => 'odl',
-        'mode'    => '0775',
       )
     }
     it {
-      should contain_file('/usr/lib/systemd/system/opendaylight.service').with(
-        'ensure'  => 'file',
-        'owner'   => 'root',
-        'group'   => 'root',
-        'mode'    => '0644',
+      should contain_file_line('routing-node').with(
+        'path'  => '/opt/opendaylight/etc/org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.startup.cfg',
+        'line'  => "routing-node=#{routing_node}",
+        'match' => '^routing-node=.*$',
       )
     }
-
-    # Verify that there are no unexpected resources from RPM-type installs
-    it { should_not contain_yumrepo('opendaylight') }
-    it { should_not contain_package('opendaylight') }
-  else
-    fail("Unexpected install method: #{method}")
   end
 end
 
-# Shared tests for unsupported OSs
-def unsupported_os_tests(expected_err_msg)
-  # Confirm that classes fail on unsupported OSs
-  it { expect { should contain_class('opendaylight') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_class('opendaylight::install') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_class('opendaylight::config') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_class('opendaylight::service') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
+# ODL username/password tests
+def username_password_tests(username, password)
 
-  # Confirm that other resources fail on unsupported OSs
-  it { expect { should contain_yumrepo('opendaylight') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_package('opendaylight') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_service('opendaylight') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
-  it { expect { should contain_file('org.apache.karaf.features.cfg') }.to raise_error(Puppet::Error, /#{expected_err_msg}/) }
+  it {
+    should contain_odl_user(username).with(
+      :password => password
+    )
+  }
 end