Improve Noop tests

* Many fixes and improvements

Related blueprint: deployment-dryrun

Change-Id: I7cdb4ea455866480a773b803f4dddd66f0fd56d1
Fuel-CI: disable
This commit is contained in:
Dmitry Ilyin 2015-04-10 17:51:52 +03:00 committed by Aleksandr Didenko
parent 073e54e093
commit 4c39102720
24 changed files with 828 additions and 245 deletions

View File

@ -6,6 +6,7 @@ group :development, :test do
gem 'rspec-puppet', '~> 2.0.0'
gem 'openstack', :require => false
gem 'netaddr', :require => false
gem 'pry'
end
if puppetversion = ENV['PUPPET_GEM_VERSION']

View File

@ -1,7 +1,7 @@
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = '--deprecation-out deprecations.log --color --format documentation'
t.rspec_opts = '--deprecation-out deprecations.log --color --tty --format documentation'
if ENV['NOOP_TEST']
t.pattern = 'spec/*/' + ENV['NOOP_TEST'] + '_spec.rb'
else
@ -10,4 +10,3 @@ RSpec::Core::RakeTask.new(:spec) do |t|
end
task :default => :spec

View File

@ -1,12 +0,0 @@
---
:backends:
- yaml
:hierarchy:
- "%{::hiera_data_globals}"
- "%{::hiera_data_astute}"
:yaml:
:datadir: "%{::hiera_data_path}"
:logger: noop

View File

@ -1,4 +0,0 @@
#!/bin/sh
DIR=`dirname $0`
cd "${DIR}" || exit 1
rspec spec/hosts/*_spec.rb spec/hosts/*/*_spec.rb

View File

@ -0,0 +1,21 @@
require 'spec_helper'
require 'shared-examples'
manifest = 'astute/enable_cinder.pp'
describe manifest do
shared_examples 'catalog' do
it "should contain cinder-volume service" do
case facts[:operatingsystem]
when 'Ubuntu'
service_name = 'cinder-volume'
when 'CentOS'
service_name = 'openstack-cinder-volume'
else
service_name = 'cinder-volume'
end
should contain_service(service_name)
end
end
test_ubuntu_and_centos manifest
end

View File

@ -0,0 +1,23 @@
require 'spec_helper'
require 'shared-examples'
manifest = 'astute/enable_compute.pp'
describe manifest do
shared_examples 'catalog' do
it "should contain nova-compute service" do
case facts[:operatingsystem]
when 'Ubuntu'
service_name = 'nova-compute'
when 'CentOS'
service_name = 'openstack-nova-compute'
else
service_name = 'nova-compute'
end
should contain_service(service_name)
end
end
test_ubuntu_and_centos manifest
end

View File

@ -3,22 +3,21 @@ require 'shared-examples'
manifest = 'ceilometer/controller.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
# TODO All this stuff should be moved to shared examples controller* tests.
settings = Noop.fuel_settings
internal_address = Noop.node_hash['internal_address']
rabbit_user = settings['rabbit']['user'] || 'nova'
use_neutron = settings['quantum'].to_s
rabbit_user = Noop.hiera_structure 'rabbit/user', 'nova'
rabbit_password = Noop.hiera_structure 'rabbit/password'
enabled = Noop.hiera_structure 'ceilometer/enabled'
rabbit_ha_queues = 'true'
# Ceilometer
if settings['ceilometer']['enabled']
if enabled
it 'should declare openstack::ceilometer class with correct parameters' do
should contain_class('openstack::ceilometer').with(
'amqp_user' => rabbit_user,
'amqp_password' => settings['rabbit']['password'],
'amqp_password' => rabbit_password,
'rabbit_ha_queues' => rabbit_ha_queues,
'on_controller' => 'true',
)

View File

@ -3,13 +3,14 @@ require 'shared-examples'
manifest = 'cluster-haproxy/cluster-haproxy.pp'
describe manifest do
shared_examples 'puppet catalogue' do
settings = Noop.fuel_settings
shared_examples 'catalog' do
networks = []
settings['network_scheme']['endpoints'].each{ |k,v|
endpoints = Noop.hiera_structure 'network_scheme/endpoints'
endpoints.each{ |k,v|
if v['IP'].is_a?(Array)
v['IP'].each { |ip|
networks << IPAddr.new(ip).to_s + "/" + ip.split('/')[1]
networks << IPAddr.new(ip).to_s + '/' + ip.split('/')[1]
}
end
}

View File

@ -0,0 +1,8 @@
require 'spec_helper'
require 'shared-examples'
manifest = 'fuel_pkgs/fuel_pkgs.pp'
describe manifest do
test_ubuntu_and_centos manifest
end

View File

@ -4,7 +4,7 @@ manifest = 'globals/globals.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
it { should contain_file '/etc/hiera/globals.yaml' }
it 'should save the globals yaml file' do
catalog = subject

View File

@ -3,11 +3,10 @@ require 'shared-examples'
manifest = 'horizon/horizon.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
settings = Noop.fuel_settings
horizon_bind_address = Noop.node_hash['internal_address']
nova_quota = settings['nova_quota']
nova_quota = Noop.hiera 'nova_quota'
# Horizon
it 'should declare openstack::horizon class' do

View File

@ -3,18 +3,18 @@ require 'shared-examples'
manifest = 'keystone/keystone.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
# TODO All this stuff should be moved to shared examples controller* tests.
settings = Noop.fuel_settings
nodes = Noop.hiera 'nodes'
internal_address = Noop.node_hash['internal_address']
primary_controller_nodes = filter_nodes(settings['nodes'],'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(settings['nodes'],'role','controller')
primary_controller_nodes = filter_nodes(nodes,'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(nodes,'role','controller')
controller_internal_addresses = nodes_to_hash(controllers,'name','internal_address')
controller_nodes = ipsort(controller_internal_addresses.values)
memcached_servers = controller_nodes.map{ |n| n = n + ':11211' }.join(',')
admin_token = settings['keystone']['admin_token']
admin_token = Noop.hiera_structure 'keystone/admin_token'
# Keystone
it 'should declare keystone class with admin_token' do

View File

@ -3,16 +3,17 @@ require 'shared-examples'
manifest = 'murano/murano.pp'
describe manifest do
shared_examples 'puppet catalogue' do
settings = Noop.fuel_settings
rabbit_user = settings['rabbit']['user'] || 'nova'
use_neutron = settings['quantum'].to_s
shared_examples 'catalog' do
rabbit_user = Noop.hiera_structure 'rabbit/user', 'nova'
rabbit_password = Noop.hiera_structure 'rabbit/password'
use_neutron = Noop.hiera 'use_neutron'
enabled = Noop.hiera_structure 'murano/enabled'
if settings['murano']['enabled']
if enabled
it 'should declare murano class correctly' do
should contain_class('murano').with(
'murano_os_rabbit_userid' => rabbit_user,
'murano_os_rabbit_passwd' => settings['rabbit']['password'],
'murano_os_rabbit_passwd' => rabbit_password,
'use_neutron' => use_neutron,
)
end

View File

@ -3,23 +3,10 @@ require 'shared-examples'
manifest = 'openstack-controller/openstack-controller.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
# TODO All this stuff should be moved to shared examples controller* tests.
settings = Noop.fuel_settings
internal_address = Noop.node_hash['internal_address']
rabbit_user = settings['rabbit']['user'] || 'nova'
use_neutron = settings['quantum'].to_s
role = settings['role']
rabbit_ha_queues = 'true'
primary_controller_nodes = filter_nodes(settings['nodes'],'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(settings['nodes'],'role','controller')
controller_internal_addresses = nodes_to_hash(controllers,'name','internal_address')
controller_nodes = ipsort(controller_internal_addresses.values)
memcached_servers = controller_nodes.map{ |n| n = n + ':11211' }.join(',')
admin_token = settings['keystone']['admin_token']
# Nova config options
it 'nova config should have report_interval set to 60' do
should contain_nova_config('DEFAULT/report_interval').with(

View File

@ -3,15 +3,15 @@ require 'shared-examples'
manifest = 'openstack-network/openstack-network-compute.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
# TODO All this stuff should be moved to shared examples controller* tests.
settings = Noop.fuel_settings
internal_address = Noop.node_hash['internal_address']
use_neutron = Noop.hiera 'use_neutron'
# Network
if settings['quantum']
if use_neutron
it 'should declare openstack::network with neutron_server parameter set to false' do
should contain_class('openstack::network').with(
'neutron_server' => 'false',
@ -25,7 +25,7 @@ describe manifest do
end
end
if settings['quantum']
if use_neutron
it 'should create /etc/libvirt/qemu.conf file that notifies libvirt service' do
should contain_file('/etc/libvirt/qemu.conf').with(
'ensure' => 'present',

View File

@ -3,27 +3,15 @@ require 'shared-examples'
manifest = 'openstack-network/openstack-network-controller.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
# TODO All this stuff should be moved to shared examples controller* tests.
settings = Noop.fuel_settings
internal_address = Noop.node_hash['internal_address']
rabbit_user = settings['rabbit']['user'] || 'nova'
use_neutron = settings['quantum'].to_s
role = settings['role']
rabbit_ha_queues = 'true'
primary_controller_nodes = filter_nodes(settings['nodes'],'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(settings['nodes'],'role','controller')
controller_internal_addresses = nodes_to_hash(controllers,'name','internal_address')
controller_nodes = ipsort(controller_internal_addresses.values)
memcached_servers = controller_nodes.map{ |n| n = n + ':11211' }.join(',')
horizon_bind_address = internal_address
admin_token = settings['keystone']['admin_token']
nova_quota = settings['nova_quota']
use_neutron = Noop.hiera 'use_neutron'
ceilometer_enabled = Noop.hiera_structure 'ceilometer/enabled'
# Network
if settings['quantum']
if use_neutron
it 'should declare openstack::network with neutron enabled' do
should contain_class('openstack::network').with(
'neutron_server' => 'true',
@ -38,13 +26,11 @@ describe manifest do
end
# Ceilometer
if settings['ceilometer']['enabled']
if use_neutron == 'true'
it 'should configure notification_driver for neutron' do
should contain_neutron_config('DEFAULT/notification_driver').with(
'value' => 'messaging',
)
end
if ceilometer_enabled and use_neutron
it 'should configure notification_driver for neutron' do
should contain_neutron_config('DEFAULT/notification_driver').with(
'value' => 'messaging',
)
end
end
end # end of shared_examples

View File

@ -3,11 +3,7 @@ require 'shared-examples'
manifest = 'roles/compute.pp'
describe manifest do
shared_examples 'puppet catalogue' do
use_neutron = Noop.fuel_settings['quantum'].to_s
internal_address = Noop.node_hash['internal_address']
shared_examples 'catalog' do
# Libvirtd.conf
it 'should configure listen_tls, listen_tcp and auth_tcp in libvirtd.conf' do

View File

@ -3,7 +3,7 @@ require 'shared-examples'
manifest = 'roles/controller.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
it 'should set vm.swappiness sysctl to 10' do
should contain_sysctl('vm.swappiness').with(

View File

@ -3,17 +3,19 @@ require 'shared-examples'
manifest = 'sahara/sahara.pp'
describe manifest do
shared_examples 'puppet catalogue' do
shared_examples 'catalog' do
settings = Noop.fuel_settings
use_neutron = settings['quantum'].to_s
use_neutron = Noop.hiera 'use_neutron'
enabled = Noop.hiera_structure 'sahara/enabled'
db_password = Noop.hiera_structure 'sahara/db_password'
user_password = Noop.hiera_structure 'sahara/user_password'
# Sahara
if settings['sahara']['enabled']
if enabled
it 'should declare sahara class correctly' do
should contain_class('sahara').with(
'db_password' => settings['sahara']['db_password'],
'keystone_password' => settings['sahara']['user_password'],
'db_password' => db_password,
'keystone_password' => user_password,
'use_neutron' => use_neutron,
'rpc_backend' => 'rabbit',
'rabbit_ha_queues' => 'true',

View File

@ -3,12 +3,12 @@ require 'shared-examples'
manifest = 'swift/swift.pp'
describe manifest do
shared_examples 'puppet catalogue' do
settings = Noop.fuel_settings
role = settings['role']
storage_hash = Noop.fuel_settings['storage']
primary_controller_nodes = filter_nodes(settings['nodes'],'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(settings['nodes'],'role','controller')
shared_examples 'catalog' do
role = Noop.hiera 'role'
storage_hash = Noop.hiera['storage']
nodes = Noop.hiera 'nodes'
primary_controller_nodes = filter_nodes(nodes,'role','primary-controller')
controllers = primary_controller_nodes + filter_nodes(nodes,'role','controller')
controller_internal_addresses = nodes_to_hash(controllers,'name','internal_address')
controller_nodes = ipsort(controller_internal_addresses.values)
memcached_servers = controller_nodes.map{ |n| n = n + ':11211' }

View File

@ -19,9 +19,9 @@ def ipsort (ips)
ips.sort { |a,b| IPAddr.new( a ) <=> IPAddr.new( b ) }
end
def test_ubuntu_and_centos(manifest)
def test_ubuntu_and_centos(manifest, force_manifest = false)
# check if task is present in the task list
unless Noop.manifest_present? manifest
unless force_manifest or Noop.manifest_present? manifest
# puts "Manifest '#{manifest}' is not enabled on the node '#{Noop.hostname}'. Skipping tests."
return
end
@ -37,9 +37,8 @@ def test_ubuntu_and_centos(manifest)
os
end
shared_examples 'should_compile' do
# it { puts "OS: '#{os}'\nYAML: '#{Noop.astute_yaml_base}'\nManifest: '#{Noop.manifest}'"}
it {
shared_examples 'compile' do
it do
File.stubs(:exists?).with('/var/lib/astute/ceph/ceph').returns(true)
File.stubs(:exists?).with('/var/lib/astute/mongodb/mongodb.key').returns(true)
File.stubs(:exists?).with('/var/lib/astute/mongodb/mongodb.key').returns(true)
@ -47,8 +46,8 @@ def test_ubuntu_and_centos(manifest)
File.stubs(:exists?).with('/var/lib/astute/nova/nova').returns(true)
File.stubs(:exists?).with('/var/lib/astute/ceph/ceph').returns(true)
File.stubs(:exists?).returns(false)
should compile
}
should compile.with_all_deps
end
end
shared_examples 'save_files_list' do
@ -58,7 +57,7 @@ def test_ubuntu_and_centos(manifest)
file_resources = {}
catalog.resources.each do |resource|
next unless resource.type == 'File'
next unless %w(present file).include? resource[:ensure] or not resource[:ensure]
next unless %w(present file directory).include? resource[:ensure] or not resource[:ensure]
if resource[:source]
content = resource[:source]
@ -92,36 +91,78 @@ def test_ubuntu_and_centos(manifest)
end
end
shared_examples 'debug' do
it 'shows catalog contents' do
Noop.show_catalog subject
end
end
shared_examples 'generate' do
it 'shows catalog contents' do
Noop.catalog_to_spec subject
end
end
shared_examples 'status' do
it 'shows status' do
puts <<-eos
=============================================
OS: #{os}
YAML: #{Noop.astute_yaml_base}
Manifest: #{Noop.manifest}
Node: #{Noop.fqdn}
Role: #{Noop.hiera 'role'}
=============================================
eos
end
end
#######################################
# Testing on different operating systems
# Ubuntu
context 'on Ubuntu platforms' do
let(:facts) { Noop.ubuntu_facts }
it_behaves_like 'should_compile'
if ENV['NOOP_SAVE_RESOURCES_DIR'] and File.directory?(ENV['NOOP_SAVE_RESOURCES_DIR'])
it_behaves_like 'save_files_list'
it_behaves_like 'save_packages_list'
end
begin
it_behaves_like 'puppet catalogue'
rescue ArgumentError
true
if Noop.test_ubuntu?
context 'on Ubuntu platforms' do
let(:facts) { Noop.ubuntu_facts }
it_behaves_like 'compile'
it_behaves_like 'status' if ENV['SPEC_SHOW_STATUS']
it_behaves_like 'debug' if ENV['SPEC_CATALOG_DEBUG']
it_behaves_like 'generate' if ENV['SPEC_SPEC_GENERATE']
it_behaves_like 'save_files_list' if ENV['SPEC_SAVE_FILE_RESOURCES']
it_behaves_like 'save_packages_list'if ENV['SPEC_SAVE_PACKAGE_RESOURCES']
begin
it_behaves_like 'catalog'
rescue ArgumentError
true
end
at_exit { RSpec::Puppet::Coverage.report! } if ENV['SPEC_COVERAGE']
end
end
# CentOS
context 'on CentOS platforms' do
let(:facts) { Noop.centos_facts }
it_behaves_like 'should_compile'
if ENV['NOOP_SAVE_RESOURCES_DIR'] and File.directory?(ENV['NOOP_SAVE_RESOURCES_DIR'])
it_behaves_like 'save_files_list'
it_behaves_like 'save_packages_list'
end
begin
it_behaves_like 'puppet catalogue'
rescue ArgumentError
true
if Noop.test_centos?
context 'on CentOS platforms' do
let(:facts) { Noop.centos_facts }
it_behaves_like 'compile'
it_behaves_like 'status' if ENV['SPEC_SHOW_STATUS']
it_behaves_like 'debug' if ENV['SPEC_CATALOG_DEBUG']
it_behaves_like 'generate' if ENV['SPEC_SPEC_GENERATE']
it_behaves_like 'save_files_list' if ENV['SPEC_SAVE_FILE_RESOURCES']
it_behaves_like 'save_packages_list'if ENV['SPEC_SAVE_PACKAGE_RESOURCES']
begin
it_behaves_like 'catalog'
rescue ArgumentError
true
end
at_exit { RSpec::Puppet::Coverage.report! } if ENV['SPEC_COVERAGE']
end
end
end

View File

@ -1,9 +1,11 @@
require 'rubygems'
require 'puppet'
require 'hiera_puppet'
require 'rspec-puppet'
require 'puppetlabs_spec_helper/module_spec_helper'
require 'yaml'
puppet_logs_dir = ENV['PUPPET_LOGS_DIR'] || 'none'
require 'fileutils'
require 'find'
module Noop
def self.module_path
@ -12,6 +14,7 @@ module Noop
end
def self.hiera_data_path
return ENV['SPEC_YAML_DIR'] if ENV['SPEC_YAML_DIR'] and File.directory? ENV['SPEC_YAML_DIR']
return @hiera_data_path if @hiera_data_path
@hiera_data_path = File.expand_path(File.join(__FILE__, '..', '..', 'astute.yaml'))
end
@ -22,7 +25,16 @@ module Noop
end
def self.astute_yaml_name
ENV['astute_filename'] || 'neut_vlan.primary-controller.yaml'
ENV['astute_filename'] || 'novanet-primary-controller.yaml'
end
def self.puppet_logs_dir
ENV['PUPPET_LOGS_DIR']
end
def self.puppet_log_file
name = manifest.gsub(/\s+|\//, '_').gsub(/\(|\)/, '') + '.log'
File.join puppet_logs_dir, name
end
def self.astute_yaml_base
@ -37,6 +49,18 @@ module Noop
File.expand_path File.join(self.hiera_data_path, self.globlas_prefix + self.astute_yaml_name)
end
def self.tasks
return @tasks if @tasks
@tasks = []
Find.find(self.module_path) do |file|
next unless File.file? file
next unless file.end_with? 'tasks.yaml'
task = YAML.load_file(file)
@tasks += task if task.is_a? Array
end
@tasks
end
def self.globlas_prefix
'globals_yaml_for_'
end
@ -49,16 +73,14 @@ module Noop
self.globlas_prefix + self.hiera_data_astute
end
def self.hiera_config_file
File.join self.fixtures_path, 'hiera.yaml'
end
def self.fuel_settings
YAML.load_file self.astute_yaml_path
end
def self.fqdn
self.fuel_settings['fqdn']
fqdn = hiera 'fqdn'
raise 'Unable to get FQDN from Hiera!' unless fqdn
fqdn
end
def self.role
hiera 'role'
end
def self.hostname
@ -66,20 +88,85 @@ module Noop
end
def self.node_hash
Noop.fuel_settings['nodes'].find { |node| node['fqdn'] == Noop.fqdn } || {}
hiera('nodes').find { |node| node['fqdn'] == fqdn } || {}
end
def self.manifest_present?(manifest)
manifest_path = File.join self.modular_manifests_node_dir, manifest
self.fuel_settings['tasks'].find do |task|
task['parameters']['puppet_manifest'] == manifest_path
tasks.each do |task|
next unless task['type'] == 'puppet'
next unless task['parameters']['puppet_manifest'] == manifest_path
if task['role']
return true if task['role'] == '*'
return true if task['role'].include?(role)
end
if task['groups']
return true if task['groups'] == '*'
return true if task['groups'].include?(role)
end
end
false
end
def self.hiera_config
{
:backends=> [
'yaml',
],
:yaml=>{
:datadir => hiera_data_path,
},
:hierarchy=> [
hiera_data_globals,
hiera_data_astute,
],
:logger => 'noop',
}
end
def self.hiera_object
Hiera.new(:config => hiera_config)
end
def self.hiera(key, default = nil)
hiera_object.lookup key, default, {}
end
def self.hiera_structure(key, default=nil)
path_lookup = lambda do |data, path, default_value|
break default_value unless data
break data unless path.is_a? Array and path.any?
break default_value unless data.is_a? Hash or data.is_a? Array
key = path.shift
if data.is_a? Array
begin
key = Integer key
rescue ArgumentError
break default_value
end
end
path_lookup.call data[key], path, default_value
end
path = key.split '/'
key = path.shift
data = hiera key
path_lookup.call data, path, default
end
def self.hiera_puppet_override
class << HieraPuppet
def hiera
Noop.hiera_object
end
end
end
def self.ubuntu_facts
{
:fqdn => self.fqdn,
:hostname => self.hostname,
:fqdn => fqdn,
:hostname => hostname,
:processorcount => '4',
:memorysize_mb => '32138.66',
:memorysize => '31.39 GB',
@ -88,21 +175,17 @@ module Noop
:operatingsystem => 'Ubuntu',
:operatingsystemrelease => '14.04',
:lsbdistid => 'Ubuntu',
:l3_fqdn_hostname => self.hostname,
:l3_fqdn_hostname => hostname,
:l3_default_route => '172.16.1.1',
:concat_basedir => '/tmp/',
:hiera_data_path => self.hiera_data_path,
:hiera_data_globals => self.hiera_data_globals,
:hiera_data_astute => self.hiera_data_astute,
:hiera_config_file => self.hiera_config_file,
:l23_os => 'ubuntu',
}
end
def self.centos_facts
{
:fqdn => self.fqdn,
:hostname => self.hostname,
:fqdn => fqdn,
:hostname => hostname,
:processorcount => '4',
:memorysize_mb => '32138.66',
:memorysize => '31.39 GB',
@ -111,13 +194,9 @@ module Noop
:operatingsystem => 'CentOS',
:operatingsystemrelease => '6.5',
:lsbdistid => 'CentOS',
:l3_fqdn_hostname => self.hostname,
:l3_fqdn_hostname => hostname,
:l3_default_route => '172.16.1.1',
:concat_basedir => '/tmp/',
:hiera_data_path => self.hiera_data_path,
:hiera_data_globals => self.hiera_data_globals,
:hiera_data_astute => self.hiera_data_astute,
:hiera_config_file => self.hiera_config_file,
:l23_os => 'centos6',
}
end
@ -132,16 +211,31 @@ module Noop
def self.manifest=(manifest)
RSpec.configuration.manifest = File.join self.modular_manifests_local_dir, manifest
@manifest = manifest
end
def self.manifest_path
RSpec.configuration.manifest
end
def self.manifest
RSpec.configuration.manifest
@manifest
end
def self.test_ubuntu?
return true unless ENV['SPEC_TEST_UBUNTU'] or ENV['SPEC_TEST_CENTOS']
true if ENV['SPEC_TEST_UBUNTU']
end
def self.test_centos?
return true unless ENV['SPEC_TEST_UBUNTU'] or ENV['SPEC_TEST_CENTOS']
true if ENV['SPEC_TEST_CENTOS']
end
## File resources list ##
def self.file_resources_lists_dir
File.expand_path File.join ENV['NOOP_SAVE_RESOURCES_DIR'], 'file_resources', self.astute_yaml_base
File.expand_path File.join ENV['SPEC_SAVE_FILE_RESOURCES'], self.astute_yaml_base
end
def self.file_resources_list_file(manifest, os)
@ -151,8 +245,8 @@ module Noop
def self.save_file_resources_list(data, manifest, os)
begin
Dir.mkdir file_resources_lists_dir unless File.directory? file_resources_lists_dir
file_path = file_resources_list_file manifest, os
FileUtils.mkdir_p file_resources_lists_dir unless File.directory? file_resources_lists_dir
File.open(file_path, 'w') do |list_file|
YAML.dump(data, list_file)
end
@ -166,7 +260,7 @@ module Noop
## Package resources list ##
def self.package_resources_lists_dir
File.expand_path File.join ENV['NOOP_SAVE_RESOURCES_DIR'], 'package_resources', self.astute_yaml_base
File.expand_path File.join ENV['SPEC_SAVE_PACKAGE_RESOURCES'], self.astute_yaml_base
end
def self.package_resources_list_file(manifest, os)
@ -176,8 +270,8 @@ module Noop
def self.save_package_resources_list(data, manifest, os)
begin
Dir.mkdir package_resources_lists_dir unless File.directory? package_resources_lists_dir
file_path = package_resources_list_file manifest, os
FileUtils.mkdir_p package_resources_lists_dir unless File.directory? package_resources_lists_dir
File.open(file_path, 'w') do |list_file|
YAML.dump(data, list_file)
end
@ -188,6 +282,40 @@ module Noop
end
end
def self.show_catalog(subject)
catalog = subject
catalog = subject.call if subject.is_a? Proc
catalog.resources.each do |resource|
puts '=' * 70
puts resource.to_manifest
end
end
def self.resource_test_template(binding)
template = <<-'eof'
it do
expect(subject).to contain_<%= resource.type.gsub('::', '__').downcase %>('<%= resource.title %>').with(
<% max_length = resource.to_hash.keys.inject(0) { |ml, key| key = key.to_s; ml = key.size if key.size > ml; ml } -%>
<% resource.each do |parameter, value| -%>
<%= ":#{parameter}".to_s.ljust(max_length + 1) %> => <%= value.inspect %>,
<% end -%>
)
end
eof
ERB.new(template, nil, '-').result(binding)
end
def self.catalog_to_spec(subject)
catalog = subject
catalog = subject.call if subject.is_a? Proc
catalog.resources.each do |resource|
next if %w(Stage Anchor).include? resource.type
next if resource.type == 'Class' and %w(Settings main).include? resource.title.to_s
puts resource_test_template binding
end
end
end
# Add fixture lib dirs to LOAD_PATH. Work-around for PUP-3336
@ -199,38 +327,37 @@ end
RSpec.configure do |c|
c.module_path = Noop.module_path
c.hiera_config = Noop.hiera_config_file
c.expose_current_running_example_as :example
c.pattern = 'hosts/**'
c.before :each do |test|
c.before :each do
# avoid "Only root can execute commands as other users"
Puppet.features.stubs(:root? => true)
# clear cached facts
Facter::Util::Loader.any_instance.stubs(:load_all)
Facter.clear
Facter.clear_messages
# Puppet logs creation
if puppet_logs_dir != 'none'
descr = test.metadata[:example_group][:full_description].gsub(/\s+|\//, '_').gsub(/\(|\)/, '')
@file = "#{puppet_logs_dir}/#{descr}.log"
Puppet::Util::Log.newdestination(@file)
if Noop.puppet_logs_dir
Puppet::Util::Log.newdestination(Noop.puppet_log_file)
Puppet::Util::Log.level = :debug
end
end
c.after :each do |test|
c.after :each do
# Puppet logs cleanup
if puppet_logs_dir != 'none'
if Noop.puppet_logs_dir
Puppet::Util::Log.close_all
descr = test.metadata[:example_group][:full_description].gsub(/\s+|\//, '_').gsub(/\(|\)|/, '')
if example.exception == nil
# Remove puppet log if there are no compilation errors
File.delete("#{puppet_logs_dir}/#{descr}.log")
# Remove puppet log if there are no compilation errors
unless example.exception
File.unlink Noop.puppet_log_file if File.file? Noop.puppet_log_file
end
end
end
end
Noop.hiera_puppet_override

470
utils/jenkins/fuel_noop_tests.rb Executable file
View File

@ -0,0 +1,470 @@
#!/usr/bin/env ruby
# Copyright 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
require 'rubygems'
require 'find'
require 'optparse'
module NoopTests
GLOBALS_SPEC = 'globals/globals_spec.rb'
RSPEC_OPTIONS = '--format documentation --color --tty --backtrace'
ASTUTE_YAML_VAR = 'astute_filename'
BUNDLE_DIR = '.bundled_gems'
BUNDLE_VAR = 'GEM_HOME'
GLOBALS_PREFIX = 'globals_yaml_for_'
PUPPET_GEM_VERSION = '~> 3.4.0'
TEST_LIBRARY_DIR = 'spec/hosts'
def self.options
return @options if @options
@options = {}
optparse = OptionParser.new do|opts|
opts.separator 'Main options:'
opts.on('-b', '--bundle', 'Use bundle to setup environment') do
@options[:bundle] = true
end
opts.on('-m', '--missing', 'Find missing spec files') do
@options[:missing_specs] = true
end
opts.on('-i', '--individually', 'Run each spec individually') do
@options[:run_individually] = true
end
opts.on('-p', '--purge_globals', 'Purge globals yaml files') do
@options[:purge_globals] = true
end
opts.on('-a', '--astute_yaml_dir DIR', 'Path to astute_yaml folder') do |dir|
@options[:astute_yaml_dir] = dir
ENV['SPEC_YAML_DIR'] = dir
end
opts.on('-Y', '--list_yamls', 'List all astute yaml files') do
@options[:list_yamls] = true
end
opts.on('-S', '--list_specs', 'List all noop spec files') do
@options[:list_specs] = true
end
opts.separator 'Filter options:'
opts.on('-s', '--specs SPEC1,SPEC2', Array, 'Run only these specs') do |specs|
@options[:filter_specs] = specs
end
opts.on('-y', '--yamls YAML1,YAML2', Array, 'Run only these yamls') do |yamls|
@options[:filter_yamls] = yamls
end
opts.on('-e', '--examples STR1,STR2', Array, 'Run only these exemples') do |examples|
@options[:filter_examples] = examples
end
opts.separator 'Debug options:'
opts.on('-c', '--console', 'Run PRY console') do
@options[:console] = true
end
opts.on('-d', '--debug', 'Show debug') do
@options[:debug] = true
end
opts.separator 'Spec options:'
opts.on('-F', '--file_resources DIR', 'Save file resources to this dir') do |dir|
ENV['SPEC_SAVE_FILE_RESOURCES'] = dir
end
opts.on('-P', '--package_resources DIR', 'Save package resources to this dir') do |dir|
ENV['SPEC_SAVE_PACKAGE_RESOURCES'] = dir
end
opts.on('-C', '--catalog_debug', 'Show catalog debug output') do
ENV['SPEC_CATALOG_DEBUG'] = 'YES'
end
opts.on('-G', '--spec_generate', 'Generate specs for catalogs') do
ENV['SPEC_SPEC_GENERATE'] = 'YES'
end
opts.on('-T', '--spec_status', 'Show spec status blocks') do
ENV['SPEC_SHOW_STATUS'] = 'YES'
end
opts.on('-O', '--spec_coverage', 'Show spec coverage statistics') do
ENV['SPEC_COVERAGE'] = 'YES'
end
opts.on('-D', '--test_ubuntu', 'Run tests for Ubuntu facts') do
ENV['SPEC_TEST_UBUNTU'] = 'YES'
end
opts.on('-R', '--test_centos', 'Run tests for CentOS facts') do
ENV['SPEC_TEST_CENTOS'] = 'YES'
end
opts.on('-L', '--puppet_logs_dir DIR', 'Save Puppet logs in this directory') do |dir|
ENV['PUPPET_LOGS_DIR'] = dir
@options[:puppet_logs_dir] = dir
end
end
optparse.parse!
@options
end
# PATHS #
# workspace directory where gem bundle will be created
# is passed from Jenkins or default value is used
# @@return [String]
def self.workspace
workspace = ENV['WORKSPACE']
unless workspace
workspace = '/tmp/noop'
Dir.mkdir workspace unless File.directory? workspace
end
unless File.directory? workspace
raise "Workspace '#{workspace}' is not a directory!"
end
workspace
end
# the root directory of noop tests
# @return [String]
def self.noop_tests_directory
return @noop_tests_directory if @noop_tests_directory
@noop_tests_directory = File.expand_path File.absolute_path File.join File.dirname(__FILE__), '..', '..', 'tests', 'noop'
end
# the folder where astute yaml files are found
# can be overridden by options
# @return [String]
def self.astute_yaml_directory
return options[:astute_yaml_dir] if options[:astute_yaml_dir] and File.directory? options[:astute_yaml_dir]
File.join noop_tests_directory, 'astute.yaml'
end
# the directory where actual tests library is found
# @return [String]
def self.test_spec_directory
File.join noop_tests_directory, TEST_LIBRARY_DIR
end
# the directory where the library of modular tasks can be found
# @return [String]
def self.modular_tasks_directory
File.expand_path File.join File.dirname(__FILE__), '..', '..', 'deployment', 'puppet', 'osnailyfacter', 'modular'
end
# LISTERS #
# find all modular task files
# @return [Array<String>]
def self.modular_puppet_task_files
files = []
Find.find(modular_tasks_directory) do |file|
next unless File.file? file
next unless file.end_with? '.pp'
file.gsub! modular_tasks_directory + '/', ''
files << file
end
files
end
# find all astute yaml files
# @return [Array<String>]
def self.astute_yaml_files
files = []
Dir.new(astute_yaml_directory).each do |file|
next if file.start_with? GLOBALS_PREFIX
next unless file.end_with? '.yaml'
files << file
end
files
end
# find all noop spec files
# @return [Array<String>]
def self.noop_spec_files
files = []
Find.find(test_spec_directory) do |file|
next unless File.file? file
next unless file.end_with? '_spec.rb'
file.gsub! test_spec_directory + '/', ''
files << file
end
files
end
# ACTIONS #
# run the code block inside the tests directory
# and then return back
def self.inside_noop_tests_directory
current_directory = Dir.pwd
Dir.chdir noop_tests_directory
result = yield
Dir.chdir current_directory if current_directory
result
end
# find all modular tasks that have no corresponding specs
# @return [Array<String>]
def self.puppet_tasks_without_specs
tasks = []
modular_puppet_task_files.each do |task|
spec = task.gsub '.pp', '_spec.rb'
spec_path = File.join test_spec_directory, spec
tasks << task unless File.exist? spec_path
end
tasks
end
# append relative path prefix to a spec name
# @param [String] spec Spec name
# @return [String]
def self.spec_path(spec)
"'#{File.join TEST_LIBRARY_DIR, spec}'"
end
# run the rspec commands with some options
# return: [ success, report ]
# @param [String] spec Spec file or pattern
# @return [Array<TrueClass,FalseClass,NilClass>] success and empty report array
def self.rspec(spec)
inside_noop_tests_directory do
command = "rspec #{RSPEC_OPTIONS} #{spec}"
command = 'bundle exec ' + command if options[:bundle]
if options[:filter_examples]
options[:filter_examples].each do |example|
command = command + " -e #{example}"
end
end
if options[:puppet_logs_dir]
command = command + " --deprecation-out #{File.join options[:puppet_logs_dir], 'deprecations.log'}"
end
debug "RUN: #{command}"
system command
[ $?.exitstatus == 0, nil ]
end
end
# run all specs together using pattern
# return: [ success, report ]
# @return [Array<TrueClass,FalseClass,NilClass>] success and empty report array
def self.run_all_specs
include_prefix = '--pattern'
exclude_prefix = '--exclude-pattern'
exclude_pattern = "#{exclude_prefix} #{spec_path GLOBALS_SPEC}"
if options[:filter_specs]
include_pattern = "#{include_prefix} #{options[:filter_specs].map { |s| spec_path s }.join ','}"
else
include_pattern = "#{include_prefix} #{spec_path '**/*_spec.rb'}"
end
rspec "#{exclude_pattern} #{include_pattern}"
end
# run the globals task for the given yaml file
# if there is no globals yaml already present
# @param [String] astute_yaml YAML file
def self.globals(astute_yaml)
globals_file = File.join astute_yaml_directory, GLOBALS_PREFIX + astute_yaml
return true if File.file? globals_file
rspec spec_path(GLOBALS_SPEC)
end
# output a debug line is debug is enabled
# @param [String] msg The message line
def self.debug(msg)
puts msg if options[:debug]
end
# decide if this spec should be included
# @param [String] spec Spec file
# @return [TrueClass,FalseClass]
def self.filter_specs(spec)
return false if spec == GLOBALS_SPEC
return true unless options[:filter_specs]
options[:filter_specs].include? spec
end
# decide if this yaml should be included
# @param [String] yaml Yaml file
# @return [TrueClass,FalseClass]
def self.filter_yamls(yaml)
return true unless options[:filter_yamls]
options[:filter_yamls].map { |y| y.gsub('.yaml', '') }.include? yaml.gsub('.yaml', '')
end
# trigger skip of the current yaml file
# when individual run is enabled
# second trigger forces exit
def self.skip
raise SystemExit if @skip
@skip = true
end
# run the code block for every astute yaml file
# return [ global success, Hash of reports for every yaml ]
# @return [Array<TrueClass,FalseClass,Hash>]
def self.for_every_astute_yaml
prepare_bundle if options[:bundle]
results = {}
errors = 0
astute_yaml_files.each do |astute_yaml|
next unless filter_yamls astute_yaml
ENV[ASTUTE_YAML_VAR] = astute_yaml
debug "=== YAML: '#{astute_yaml}' ==="
globals astute_yaml
success, report = yield
errors += 1 unless success
results[astute_yaml] = {
:success => success,
:report => report,
}
end
[ errors == 0, results ]
end
# run every spec file individually
# return report for every spec
# return [ global success, Hash of reports for every spec ]
# @return [Array<TrueClass,FalseClass,Hash>]
def self.run_all_specs_individually
results = {}
errors = 0
trap('SIGINT') do
skip
end
noop_spec_files.each do |spec|
if @skip
@skip = false
debug color(31, 'Skipping current yaml file!')
return [ errors == 0, results ]
end
next if spec == GLOBALS_SPEC
next unless filter_specs spec
debug "--- SPEC: '#{spec}' ---"
success, report = rspec spec_path(spec)
errors += 1 unless success
results[spec] = {
:success => success,
:report => report,
}
end
[ errors == 0, results ]
end
# setup the bundle directory
def self.prepare_bundle
ENV['PUPPET_GEM_VERSION'] = PUPPET_GEM_VERSION unless ENV['PUPPET_GEM_VERSION']
inside_noop_tests_directory do
`bundle --version`
raise 'Bundle is not installed!' if $?.exitstatus != 0
ENV[BUNDLE_VAR] = File.join workspace, BUNDLE_DIR
system 'bundle update'
raise 'Could not prepare bundle environment!' if $?.exitstatus != 0
end
end
# add color codes to a line
# @param [Integer] code Color code
# @param [String] string Text string
def self.color(code, string)
"\033[#{code}m#{string}\033[0m"
end
def self.status_string(success)
if success
color 32, 'OK'
else
color 31, 'FAIL'
end
end
# calculate the maximum length of the hash keys
# used to align columns
# @param [Hash]
# @return [Integer]
def self.max_key_length(hash)
hash.keys.inject(0) do |ml, key|
key = key.to_s
ml = key.size if key.size > ml
ml
end
end
# output the test results
# @param [Hash]
def self.show_results(results)
max_astute_yaml_length = max_key_length results
results.each do |astute_yaml, yaml_result|
puts "-> #{astute_yaml.ljust max_astute_yaml_length} #{status_string yaml_result[:success]}"
if yaml_result[:report].is_a? Hash
max_spec_length = max_key_length yaml_result[:report]
yaml_result[:report].each do |spec, spec_result|
puts " * #{spec.ljust max_spec_length} #{status_string spec_result[:success]}"
end
end
end
end
# remove all globals yaml files
def self.purge_globals
Dir.new(astute_yaml_directory).each do |file|
path = File.join astute_yaml_directory, file
next unless File.file? path
next unless file.start_with? GLOBALS_PREFIX
next unless file.end_with? '.yaml'
debug "Remove: '#{path}'"
File.unlink path
end
end
# the main function
def self.main
if options[:console]
require 'pry'
self.pry
exit 0
end
if options[:missing_specs]
missing_specs = puppet_tasks_without_specs
if missing_specs.any?
puts color(31, "Missing specs for tasks: #{missing_specs.join ', '}")
exit missing_specs.length
end
end
if options[:list_yamls]
astute_yaml_files.each do |file|
puts file
end
exit 0
end
if options[:list_specs]
noop_spec_files.each do |file|
puts file
end
exit 0
end
if options[:purge_globals]
purge_globals
exit 0
end
success, result = for_every_astute_yaml do
if options[:run_individually]
run_all_specs_individually
else
run_all_specs
end
end
show_results result
success
end
end
NoopTests.main if __FILE__ == $0

View File

@ -1,67 +1,5 @@
#!/bin/bash
MODULAR_BASE='deployment/puppet/osnailyfacter/modular/'
if ! [ -d "$WORKSPACE" ] ; then
echo "ERROR: WORKSPACE not found"
exit 1
fi
if [ -z "$PUPPET_GEM_VERSION" ] ; then
export PUPPET_GEM_VERSION='~> 3.4.0'
fi
if [ -z "$NOOP_YAMLS" ] ; then
NOOP_YAMLS=`ls ./tests/noop/astute.yaml/*yaml`
fi
# Check for bundle and exit if failed
bundle --version || exit 1
export GEM_HOME=$WORKSPACE/.bundled_gems
# Prepare gems
pushd ./tests/noop
bundle update
popd
failed_yamls=""
untested_tasks=""
# Check that all tasks have spec tests
for i in `find $MODULAR_BASE -name *\.pp | sed -e "s#$MODULAR_BASE##"` ; do
spec="${i/\.pp/_spec.rb}"
if ! [ -f "tests/noop/spec/hosts/$spec" ] && [ "$i" != "globals/globals.pp" ] ; then
untested_tasks="${untested_tasks}\n${MODULAR_BASE}${i}"
fi
done
if ! [ -z "$untested_tasks" ] ; then
echo -e "\nFAILED. No modular rspec tests found for the following tasks:"
echo -e "$untested_tasks\n"
exit 1
fi
# Iterate over astute.yaml files we have and run tests
for YAML in $NOOP_YAMLS ; do
echo "${YAML}" | grep -q 'globals_yaml_for_'
if [ $? -eq 0 ]; then
continue
fi
export astute_filename=`basename $YAML`
echo -e "\n\n======== Running modular noop tests for $astute_filename ========\n"
pushd ./tests/noop
echo "Starting test for YAML '${astute_filename} at directory '`pwd`'"
bundle exec rake spec || failed_yamls="$failed_yamls\n$astute_filename"
popd
done
# Report and exit
if [ -z "$failed_yamls" ] ; then
echo -e "\nRSpec Noop Tests SUCCEEDED: No errors found.\n"
exit 0
else
echo -e "\nRSpec Noop Tests FAILED for the following astute.yaml files:"
echo -e "$failed_yamls\n"
exit 1
fi
DIR=`dirname $0`
"${DIR}/fuel_noop_tests.rb" -b -d -m ${@}