diff --git a/.fixtures.yml b/.fixtures.yml new file mode 100644 index 00000000..a0c519c0 --- /dev/null +++ b/.fixtures.yml @@ -0,0 +1,7 @@ +fixtures: + repositories: + stdlib: 'git://github.com/puppetlabs/puppetlabs-stdlib.git' + inifile: 'git://github.com/puppetlabs/puppetlabs-inifile' + vcsrepo: 'git://github.com/puppetlabs/puppetlabs-vcsrepo' + symlinks: + tempest: "#{source_dir}" diff --git a/.gitignore b/.gitignore index 1fc755c8..6a08cb98 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ spec/fixtures/modules/* spec/fixtures/manifests/site.pp *.swp pkg +.bundle +vendor +.vagrant +.project diff --git a/.rspec b/.rspec new file mode 100644 index 00000000..8c18f1ab --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--format documentation +--color diff --git a/Gemfile b/Gemfile index 89f2e1b2..0d35201b 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,7 @@ source 'https://rubygems.org' group :development, :test do gem 'puppetlabs_spec_helper', :require => false gem 'puppet-lint', '~> 0.3.2' + gem 'rake', '10.1.1' end if puppetversion = ENV['PUPPET_GEM_VERSION'] diff --git a/Rakefile b/Rakefile index 4c2b2ed0..fe33ec6a 100644 --- a/Rakefile +++ b/Rakefile @@ -3,4 +3,11 @@ require 'puppet-lint/tasks/puppet-lint' PuppetLint.configuration.fail_on_warnings = true PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_class_inherits_from_params_class') PuppetLint.configuration.send('disable_class_parameter_defaults') + +desc "Run lint, and spec tests." +task :test => [ + :lint, + :spec, +] diff --git a/spec/classes/tempest_spec.rb b/spec/classes/tempest_spec.rb new file mode 100644 index 00000000..ac758dd1 --- /dev/null +++ b/spec/classes/tempest_spec.rb @@ -0,0 +1,162 @@ +require 'spec_helper' + +describe 'tempest' do + shared_examples 'tempest' do + context 'without parameters' do + describe "should raise error" do + it { expect { should contain_class('tempest::params') }.to raise_error(Puppet::Error, /A value for either image_name or image_ref/) } + end + end + + context 'with image_name parameters' do + let :params do + { :image_name => 'image_name' } + end + + describe "should raise error" do + it { expect { should contain_class('tempest::params') }.to raise_error(Puppet::Error, /A value for either image_name_alt or image_ref_alt/) } + end + end + + context 'without configures images and neutron_available' do + let :params do + { :configure_images => false, + :neutron_available => true } + end + + describe "should raise error" do + it { expect { should contain_class('tempest::params') }.to raise_error(Puppet::Error, /A value for either public_network_id or public_network_name/) } + end + end + + context 'with parameters' do + let :params do + { :configure_images => true, + :image_name => 'image name', + :image_name_alt => 'image name alt', + :public_network_name => 'network name', + :neutron_available => true } + end + + describe "should install tempest" do + it 'installs packages' do + should contain_class('tempest::params') + + should contain_exec('install-pip').with( + :command => '/usr/bin/easy_install pip', + :unless => '/usr/bin/which pip', + :require => 'Package[python-setuptools]' + ) + + should contain_exec('install-tox').with( + :command => /pip install -U tox$/, + :unless => '/usr/bin/which tox', + :require => 'Exec[install-pip]' + ) + + should contain_vcsrepo('/var/lib/tempest').with( + :ensure => 'present', + :source => 'git://github.com/openstack/tempest.git', + :revision => nil, + :provider => 'git', + :require => 'Package[git]', + :user => 'root' + ) + end + + it 'load configuration' do + should contain_file('/var/lib/tempest/etc/tempest.conf').with( + :replace => false, + :source => '/var/lib/tempest/etc/tempest.conf.sample', + :require => "Vcsrepo[/var/lib/tempest]", + :owner => 'root' + ) + end + + it 'configure tempest config' do + should contain_tempest_config('compute/change_password_available').with(:value => nil) + should contain_tempest_config('compute/flavor_ref').with(:value => nil) + should contain_tempest_config('compute/flavor_ref_alt').with(:value => nil) + should contain_tempest_config('compute/image_alt_ssh_user').with(:value => nil) + should contain_tempest_config('compute/image_ref').with(:value => nil) + should contain_tempest_config('compute/image_ref_alt').with(:value => nil) + should contain_tempest_config('compute/image_ssh_user').with(:value => nil) + should contain_tempest_config('compute/resize_available').with(:value => nil) + should contain_tempest_config('identity/admin_password').with(:value => nil) + should contain_tempest_config('identity/admin_tenant_name').with(:value => nil) + should contain_tempest_config('identity/admin_username').with(:value => nil) + should contain_tempest_config('identity/admin_role').with(:value => nil) + should contain_tempest_config('identity/alt_password').with(:value => nil) + should contain_tempest_config('identity/alt_tenant_name').with(:value => nil) + should contain_tempest_config('identity/alt_username').with(:value => nil) + should contain_tempest_config('identity/password').with(:value => nil) + should contain_tempest_config('identity/tenant_name').with(:value => nil) + should contain_tempest_config('identity/uri').with(:value => nil) + should contain_tempest_config('identity/username').with(:value => nil) + should contain_tempest_config('network/public_network_id').with(:value => nil) + should contain_tempest_config('network/public_router_id').with(:value => '') + should contain_tempest_config('service_available/cinder').with(:value => true) + should contain_tempest_config('service_available/glance').with(:value => true) + should contain_tempest_config('service_available/heat').with(:value => false) + should contain_tempest_config('service_available/horizon').with(:value => true) + should contain_tempest_config('service_available/neutron').with(:value => true) + should contain_tempest_config('service_available/nova').with(:value => true) + should contain_tempest_config('service_available/swift').with(:value => false) + should contain_tempest_config('whitebox/db_uri').with(:value => nil) + end + + it 'set glance id' do + should contain_tempest_glance_id_setter('image_ref').with( + :ensure => 'present', + :tempest_conf_path => '/var/lib/tempest/etc/tempest.conf', + :image_name => 'image name', + :require => 'File[/var/lib/tempest/etc/tempest.conf]' + ) + + should contain_tempest_glance_id_setter('image_ref_alt').with( + :ensure => 'present', + :tempest_conf_path => '/var/lib/tempest/etc/tempest.conf', + :image_name => 'image name alt', + :require => 'File[/var/lib/tempest/etc/tempest.conf]' + ) + end + + it 'neutron net id' do + should contain_tempest_neutron_net_id_setter('public_network_id').with( + :ensure => 'present', + :tempest_conf_path => '/var/lib/tempest/etc/tempest.conf', + :network_name => 'network name', + :require => 'File[/var/lib/tempest/etc/tempest.conf]' + ) + end + end + end + end + + context 'on Debian platforms' do + let :facts do + { :osfamily => 'Debian' } + end + + it_behaves_like 'tempest' + end + + context 'on RedHat platforms' do + let :facts do + { :osfamily => 'RedHat' } + end + + it_behaves_like 'tempest' + end + + context 'unsupported operating system' do + describe 'tempest class without any parameters on Solaris/Nexenta' do + let :facts do + { :osfamily => 'Solaris', + :operatingsystem => 'Nexenta' } + end + + it { expect { should contain_package('tempest') }.to raise_error(Puppet::Error, /Unsupported osfamily: Solaris operatingsystem: Nexenta/) } + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/spec/unit/provider/tempest_config/ini_setting_spec.rb b/spec/unit/provider/tempest_config/ini_setting_spec.rb new file mode 100644 index 00000000..d3781863 --- /dev/null +++ b/spec/unit/provider/tempest_config/ini_setting_spec.rb @@ -0,0 +1,35 @@ +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'inifile', + 'lib') +) + +require 'spec_helper' + +provider_class = Puppet::Type.type(:tempest_config).provider(:ini_setting) +describe provider_class do + + it 'should default to the default setting when no other one is specified' do + resource = Puppet::Type::Tempest_config.new( + {:name => 'DEFAULT/foo', :value => 'bar'} + ) + provider = provider_class.new(resource) + provider.section.should == 'DEFAULT' + provider.setting.should == 'foo' + end + + it 'should allow setting to be set explicitly' do + resource = Puppet::Type::Tempest_config.new( + {:name => 'dude/foo', :value => 'bar'} + ) + provider = provider_class.new(resource) + provider.section.should == 'dude' + provider.setting.should == 'foo' + end +end diff --git a/spec/unit/type/tempest_config_spec.rb b/spec/unit/type/tempest_config_spec.rb new file mode 100644 index 00000000..aff9b364 --- /dev/null +++ b/spec/unit/type/tempest_config_spec.rb @@ -0,0 +1,53 @@ +require 'puppet' +require 'puppet/type/tempest_config' + +describe 'Puppet::Type.type(:tempest_config)' do + before :each do + @tempest_config = Puppet::Type.type(:tempest_config).new(:name => 'DEFAULT/foo', :value => 'bar') + end + + it 'should require a name' do + expect { + Puppet::Type.type(:tempest_config).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'should not expect a name with whitespace' do + expect { + Puppet::Type.type(:tempest_config).new(:name => 'f oo') + }.to raise_error(Puppet::Error, /Invalid value "f oo"/) + end + + it 'should fail when there is no section' do + expect { + Puppet::Type.type(:tempest_config).new(:name => 'foo') + }.to raise_error(Puppet::Error, /Invalid value "foo"/) + end + + it 'should not require a value when ensure is absent' do + Puppet::Type.type(:tempest_config).new(:name => 'DEFAULT/foo', :ensure => :absent) + end + + it 'should accept a valid value' do + @tempest_config[:value] = 'bar' + @tempest_config[:value].should == 'bar' + end + + it 'should not accept a value with whitespace' do + @tempest_config[:value] = 'b ar' + @tempest_config[:value].should == 'b ar' + end + + it 'should accept valid ensure values' do + @tempest_config[:ensure] = :present + @tempest_config[:ensure].should == :present + @tempest_config[:ensure] = :absent + @tempest_config[:ensure].should == :absent + end + + it 'should not accept invalid ensure values' do + expect { + @tempest_config[:ensure] = :latest + }.to raise_error(Puppet::Error, /Invalid value/) + end +end diff --git a/spec/unit/type/tempest_glance_id_setter_spec.rb b/spec/unit/type/tempest_glance_id_setter_spec.rb new file mode 100644 index 00000000..bddd2d1d --- /dev/null +++ b/spec/unit/type/tempest_glance_id_setter_spec.rb @@ -0,0 +1,31 @@ +require 'puppet' +require 'puppet/type/tempest_glance_id_setter' + +describe 'Puppet::Type.type(:tempest_glance_id_setter)' do + it 'should require a name' do + expect { + Puppet::Type.type(:tempest_glance_id_setter).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + before :each do + @tempest_glance_id_setter = Puppet::Type.type(:tempest_glance_id_setter).new( + :name => 'foo', + :tempest_conf_path => '/tmp/tempest.conf', + :image_name => 'image') + + end + + it 'should accept valid ensure values' do + @tempest_glance_id_setter[:ensure] = :present + @tempest_glance_id_setter[:ensure].should == :present + @tempest_glance_id_setter[:ensure] = :absent + @tempest_glance_id_setter[:ensure].should == :absent + end + + it 'should not accept invalid ensure values' do + expect { + @tempest_glance_id_setter[:ensure] = :installed + }.to raise_error(Puppet::Error, /Invalid value/) + end +end diff --git a/spec/unit/type/tempest_neutron_net_id_setter_spec.rb b/spec/unit/type/tempest_neutron_net_id_setter_spec.rb new file mode 100644 index 00000000..4bc40e2e --- /dev/null +++ b/spec/unit/type/tempest_neutron_net_id_setter_spec.rb @@ -0,0 +1,31 @@ +require 'puppet' +require 'puppet/type/tempest_neutron_net_id_setter' + +describe 'Puppet::Type.type(:tempest_neutron_net_id_setter)' do + it 'should require a name' do + expect { + Puppet::Type.type(:tempest_neutron_net_id_setter).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + before :each do + @tempest_neutron_net_id_setter = Puppet::Type.type(:tempest_neutron_net_id_setter).new( + :name => 'foo', + :tempest_conf_path => '/tmp/tempest.conf', + :network_name => 'image') + + end + + it 'should accept valid ensure values' do + @tempest_neutron_net_id_setter[:ensure] = :present + @tempest_neutron_net_id_setter[:ensure].should == :present + @tempest_neutron_net_id_setter[:ensure] = :absent + @tempest_neutron_net_id_setter[:ensure].should == :absent + end + + it 'should not accept invalid ensure values' do + expect { + @tempest_neutron_net_id_setter[:ensure] = :installed + }.to raise_error(Puppet::Error, /Invalid value/) + end +end diff --git a/tests/init.pp b/tests/init.pp new file mode 100644 index 00000000..88322241 --- /dev/null +++ b/tests/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +include tempest