diff --git a/.gitignore b/.gitignore
index 03c312d..ea90996 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
Gemfile.lock
-.bundled_gems
+.bundled_gems/
+log/
+junit/
+.vagrant/
diff --git a/Gemfile b/Gemfile
index 2db9fcf..f9c7a30 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,7 +13,7 @@ group :development, :test do
# Puppet 4.x related lint checks
gem 'puppet-lint-unquoted_string-check'
- #The puppet-gerrit module makes too much use of empty string defaults
+ #The puppet-jenkins module makes too much use of empty string defaults
#so disable this check for now
#gem 'puppet-lint-empty_string-check'
gem 'puppet-lint-leading_zero-check'
@@ -28,4 +28,8 @@ group :development, :test do
end
end
+group :system_tests do
+ gem 'beaker-rspec', :require => false
+end
+
# vim:ft=ruby
diff --git a/spec/acceptance/fixtures/master.pp b/spec/acceptance/fixtures/master.pp
new file mode 100644
index 0000000..70d1ad8
--- /dev/null
+++ b/spec/acceptance/fixtures/master.pp
@@ -0,0 +1,10 @@
+class { '::jenkins::jenkinsuser':
+ ssh_key => 'sshkey',
+}
+
+class { '::jenkins::master':
+ vhost_name => '127.0.0.1',
+ jenkins_ssh_private_key => file('/tmp/jenkins-ssh-keys/ssh_rsa_key'),
+ jenkins_ssh_public_key => file('/tmp/jenkins-ssh-keys/ssh_rsa_key.pub'),
+ require => Class['::jenkins::jenkinsuser'],
+}
diff --git a/spec/acceptance/fixtures/preconditions.pp b/spec/acceptance/fixtures/preconditions.pp
new file mode 100644
index 0000000..00cb514
--- /dev/null
+++ b/spec/acceptance/fixtures/preconditions.pp
@@ -0,0 +1,39 @@
+exec { 'update apt':
+ command => '/usr/bin/apt-get update',
+}
+
+# Installing ssl-cert in order to get snakeoil certs
+package { 'ssl-cert':
+ ensure => present,
+ require => Exec['update apt'],
+}
+
+vcsrepo { '/etc/project-config':
+ ensure => latest,
+ provider => git,
+ revision => 'master',
+ source => 'git://git.openstack.org/openstack-infra/project-config',
+}
+
+# Generates ssh rsa keys
+define ssh_keygen (
+ $ssh_directory = undef
+) {
+ Exec { path => '/bin:/usr/bin' }
+
+ $ssh_key_file = "${ssh_directory}/${name}"
+
+ exec { "ssh-keygen for ${name}":
+ command => "ssh-keygen -t rsa -f ${ssh_key_file} -N ''",
+ creates => $ssh_key_file,
+ }
+}
+
+$ssh_key_directory = '/tmp/jenkins-ssh-keys'
+file { $ssh_key_directory:
+ ensure => directory,
+}
+ssh_keygen { 'ssh_rsa_key':
+ ssh_directory => $ssh_key_directory,
+ require => File[$ssh_key_directory],
+}
diff --git a/spec/acceptance/fixtures/slave.pp b/spec/acceptance/fixtures/slave.pp
new file mode 100644
index 0000000..e4f562f
--- /dev/null
+++ b/spec/acceptance/fixtures/slave.pp
@@ -0,0 +1,13 @@
+class { '::jenkins::slave':
+ ssh_key => 'sshkey',
+ user => true
+}
+
+class { '::jenkins::job_builder':
+ url => 'https://127.0.0.1',
+ username => 'jenkins',
+ password => 'secret',
+ jenkins_jobs_update_timeout => 1200,
+ config_dir => '/etc/project-config/jenkins',
+ require => Class['::jenkins::slave'],
+}
diff --git a/spec/acceptance/master_spec.rb b/spec/acceptance/master_spec.rb
new file mode 100644
index 0000000..64fdc90
--- /dev/null
+++ b/spec/acceptance/master_spec.rb
@@ -0,0 +1,140 @@
+require 'spec_helper_acceptance'
+
+describe 'puppet-jenkins master module', :if => ['debian', 'ubuntu'].include?(os[:family]) do
+ def pp_path
+ base_path = File.dirname(__FILE__)
+ File.join(base_path, 'fixtures')
+ end
+
+ def preconditions_puppet_module
+ module_path = File.join(pp_path, 'preconditions.pp')
+ File.read(module_path)
+ end
+
+ def jenkins_master_puppet_module
+ module_path = File.join(pp_path, 'master.pp')
+ File.read(module_path)
+ end
+
+ before(:all) do
+ apply_manifest(preconditions_puppet_module, catch_failures: true)
+ end
+
+ it 'should work with no errors' do
+ apply_manifest(jenkins_master_puppet_module, catch_failures: true)
+ end
+
+ it 'should be idempotent' do
+ apply_manifest(jenkins_master_puppet_module, catch_changes: true)
+ end
+
+ describe 'required files' do
+ describe 'jenkins master ssh keys' do
+ describe file('/var/lib/jenkins/.ssh/id_rsa') do
+ it { should be_file }
+ its(:content) { should match '-----BEGIN RSA PRIVATE KEY-----' }
+ end
+
+ describe file('/var/lib/jenkins/.ssh/id_rsa.pub') do
+ it { should be_file }
+ its(:content) { should match 'ssh_rsa' }
+ end
+ end
+
+ describe 'files and directories belonging to jenkins user and group' do
+ files = [
+ file('/var/lib/jenkins/.ssh/id_rsa'),
+ file('/var/lib/jenkins/.ssh/id_rsa.pub'),
+ file('/var/lib/jenkins/logger.conf'),
+ file('/var/lib/jenkins/plugins/simple-theme-plugin/openstack-page-bkg.jpg'),
+ file('/var/lib/jenkins/plugins/simple-theme-plugin/openstack.css'),
+ file('/var/lib/jenkins/plugins/simple-theme-plugin/openstack.js'),
+ ]
+
+ files.each do |file|
+ describe file do
+ it { should be_file }
+ it { should be_owned_by 'jenkins' }
+ it { should be_grouped_into 'jenkins' }
+ end
+ end
+
+ directories = [
+ file('/var/lib/jenkins/.ssh'),
+ file('/var/lib/jenkins/plugins'),
+ file('/var/lib/jenkins/plugins/simple-theme-plugin'),
+ ]
+
+ directories.each do |directory|
+ describe directory do
+ it { should be_directory }
+ it { should be_owned_by 'jenkins' }
+ it { should be_grouped_into 'jenkins' }
+ end
+ end
+
+ end
+ end
+
+ describe 'required services' do
+ describe command('curl http://127.0.0.1 --verbose') do
+ its(:stdout) { should contain('302 Found') }
+ its(:stdout) { should contain('The document has moved') }
+ end
+
+ describe command('curl http://127.0.0.1 --insecure --location --verbose') do
+ its(:stdout) { should contain('Jenkins') }
+ end
+
+ describe command('curl https://127.0.0.1 --insecure') do
+ its(:stdout) { should contain('Jenkins') }
+ end
+
+ describe command('curl 127.0.0.1:8080') do
+ its(:stdout) { should contain('Jenkins') }
+ end
+ end
+
+ describe 'required packages' do
+ required_packages = [
+ package('jenkins'),
+ package('openjdk-7-jre-headless'),
+ package('python-babel'),
+ package('python-sqlalchemy'),
+ package('sqlite3'),
+ package('ssl-cert'),
+ ]
+
+ required_packages << package('apache2') if ['ubuntu', 'debian'].include?(os[:family])
+ required_packages << package('httpd') if ['centos', 'redhat'].include?(os[:family])
+
+ required_packages.each do |package|
+ describe package do
+ it { should be_installed }
+ end
+ end
+
+ unnecessary_packages = [
+ package('openjdk-6-jre-headless')
+ ]
+
+ unnecessary_packages.each do |package|
+ describe package do
+ it { should_not be_installed }
+ end
+ end
+ end
+
+ describe 'required users and groups' do
+ describe group('jenkins') do
+ it { should exist }
+ end
+
+ describe user('jenkins') do
+ it { should exist }
+ it { should belong_to_group 'jenkins' }
+ it { should have_home_directory '/home/jenkins' }
+ it { should have_login_shell '/bin/bash' }
+ end
+ end
+end
diff --git a/spec/acceptance/slave_spec.rb b/spec/acceptance/slave_spec.rb
new file mode 100644
index 0000000..49e1edf
--- /dev/null
+++ b/spec/acceptance/slave_spec.rb
@@ -0,0 +1,187 @@
+require 'spec_helper_acceptance'
+
+describe 'puppet-jenkins slave module', :if => ['debian', 'ubuntu'].include?(os[:family]) do
+ def pp_path
+ base_path = File.dirname(__FILE__)
+ File.join(base_path, 'fixtures')
+ end
+
+ def preconditions_puppet_module
+ module_path = File.join(pp_path, 'preconditions.pp')
+ File.read(module_path)
+ end
+
+ def jenkins_slave_puppet_module
+ module_path = File.join(pp_path, 'slave.pp')
+ File.read(module_path)
+ end
+
+ before(:all) do
+ apply_manifest(preconditions_puppet_module, catch_failures: true)
+ end
+
+ it 'should work with no errors' do
+ apply_manifest(jenkins_slave_puppet_module, catch_failures: true)
+ end
+
+ it 'should be idempotent' do
+ apply_manifest(jenkins_slave_puppet_module, catch_changes: true)
+ end
+
+ describe 'required files' do
+ describe file('/home/jenkins/.gitconfig') do
+ it { should be_file }
+ its(:content) { should match '[user]' }
+ its(:content) { should match 'name = OpenStack Jenkins' }
+ its(:content) { should match 'email = jenkins@openstack.org' }
+ its(:content) { should match '[gitreview]' }
+ its(:content) { should match 'username = jenkins' }
+ end
+
+ describe file('/home/jenkins/.m2/settings.xml') do
+ it { should be_file }
+ its(:content) { should match 'jenkins' }
+ its(:content) { should match 'http://repo.jenkins-ci.org/public/' }
+ end
+
+ describe file('/home/jenkins/.ssh/config') do
+ it { should be_file }
+ its(:content) { should match 'StrictHostKeyChecking=no' }
+ end
+
+ jenkins_user_directories = [
+ file('/home/jenkins/.pip'),
+ file('/home/jenkins/.config'),
+ ]
+
+ jenkins_user_directories.each do |directory|
+ describe directory do
+ it { should be_directory }
+ it { should be_owned_by 'jenkins' }
+ it { should be_grouped_into 'jenkins' }
+ end
+ end
+
+ jenkins_user_files = [
+ file('/home/jenkins/.bash_logout'),
+ file('/home/jenkins/.bashrc'),
+ file('/home/jenkins/.gnupg/pubring.gpg'),
+ file('/home/jenkins/.profile'),
+ file('/home/jenkins/.ssh/authorized_keys'),
+ ]
+
+ jenkins_user_files.each do |file|
+ describe file do
+ it { should be_file }
+ end
+ end
+
+ describe 'symlinkies' do
+ symlinkies = {
+ file('/usr/local/bin/c++') => '/usr/bin/ccache',
+ file('/usr/local/bin/cc') => '/usr/bin/ccache',
+ file('/usr/local/bin/g++') => '/usr/bin/ccache',
+ file('/usr/local/bin/gcc') => '/usr/bin/ccache',
+ }
+
+ symlinkies.each do |link, destination|
+ describe link do
+ it { should be_symlink }
+ it { should be_linked_to destination }
+ end
+ end
+ end
+
+ describe file('/usr/local/jenkins') do
+ it { should be_directory }
+ it { should be_owned_by 'root' }
+ it { should be_grouped_into 'root' }
+ end
+ end
+
+ describe 'required packages' do
+ if ['ubuntu', 'debian'].include?(os[:family]) then
+ required_packages = [
+ package('build-essential'),
+ package('ccache'),
+ package('maven2'),
+ package('openjdk-7-jdk'),
+ package('python-netaddr'),
+ package('ruby1.9.1'),
+ ]
+ elsif ['centos', 'redhat'].include?(os[:family]) then
+ required_packages = [
+ package('ccache'),
+ package('java-1.7.0-openjdk-devel'),
+ package('python-netaddr'),
+ ]
+ end
+
+ required_packages.each do |package|
+ describe package do
+ it { should be_installed }
+ end
+ end
+
+ unnecessary_packages = [
+ package('openjdk-6-jre-headless')
+ ]
+
+ unnecessary_packages.each do |package|
+ describe package do
+ it { should_not be_installed }
+ end
+ end
+
+ pip_packages = [
+ package('git-review'),
+ package('tox'),
+ ]
+
+ pip_packages.each do |package|
+ describe package do
+ it { should be_installed.by('pip') }
+ end
+ end
+ end
+
+ describe 'required users and groups' do
+ describe group('jenkins') do
+ it { should exist }
+ end
+
+ describe user('jenkins') do
+ it { should exist }
+ it { should belong_to_group 'jenkins' }
+ it { should have_home_directory '/home/jenkins' }
+ it { should have_login_shell '/bin/bash' }
+ end
+ end
+end
+
+describe 'puppet-jenkins jenkins-job-builder module', :if => ['debian', 'ubuntu'].include?(os[:family]) do
+ describe 'required files' do
+ describe file('/etc/jenkins_jobs/jenkins_jobs.ini') do
+ its(:content) { should match '[jenkins]' }
+ its(:content) { should match 'user=jenkins' }
+ its(:content) { should match 'password=secret' }
+ its(:content) { should match 'url=https://127.0.0.1' }
+ end
+
+ describe file('/etc/jenkins_jobs/config') do
+ it { should be_directory }
+ it { should be_owned_by 'root' }
+ it { should be_grouped_into 'root' }
+ end
+ end
+
+ describe 'required packages' do
+ describe package('python-jenkins') do
+ it { should be_installed.by('pip') }
+ end
+
+ describe package('python-yaml') do
+ it { should be_installed }
+ end
+ end
+end