![Vladimir Kuklin](/assets/img/avatar_default.png)
1) Add test to check whether catalog contains injection of files which actually should be installed as packages 2) Add more fixtures with astute yamls 3) Shared examples structure refactoring 4) Remove File.exists? checks from install_ssh_keys 5) Add rspec and puppet debug options 6) Misc fixes to make rspec actually work Change-Id: I8217594cd9f2c0f19c840c0abed37d94ff80eb75 blueprint: package-fuel-components
407 lines
11 KiB
Ruby
407 lines
11 KiB
Ruby
require 'rubygems'
|
|
require 'puppet'
|
|
require 'hiera_puppet'
|
|
require 'rspec-puppet'
|
|
require 'puppetlabs_spec_helper/module_spec_helper'
|
|
require 'yaml'
|
|
require 'fileutils'
|
|
require 'find'
|
|
|
|
module Noop
|
|
def self.module_path
|
|
return @module_path if @module_path
|
|
@module_path = File.expand_path(File.join(__FILE__, '..', '..', '..', '..', 'deployment', 'puppet'))
|
|
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
|
|
|
|
def self.fixtures_path
|
|
return @fixtures_path if @fixtures_path
|
|
@fixtures_path = File.expand_path(File.join(__FILE__, '..', '..', 'fixtures'))
|
|
end
|
|
|
|
def self.spec_path
|
|
return @spec_path if @spec_path
|
|
@spec_path = File.expand_path(File.join(__FILE__, '..', 'hosts'))
|
|
end
|
|
|
|
def self.astute_yaml_name
|
|
ENV['SPEC_ASTUTE_FILE_NAME'] || 'novanet-primary-controller.yaml'
|
|
end
|
|
|
|
def self.puppet_logs_dir
|
|
ENV['SPEC_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
|
|
File.basename(self.astute_yaml_name).gsub(/.yaml$/, '')
|
|
end
|
|
|
|
def self.astute_yaml_path
|
|
File.expand_path File.join(self.hiera_data_path, self.astute_yaml_name)
|
|
end
|
|
|
|
def self.globals_yaml_path
|
|
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
|
|
|
|
def self.hiera_data_astute
|
|
self.astute_yaml_base
|
|
end
|
|
|
|
def self.hiera_data_globals
|
|
self.globlas_prefix + self.hiera_data_astute
|
|
end
|
|
|
|
def self.fqdn
|
|
fqdn = hiera 'fqdn'
|
|
raise 'Unable to get FQDN from Hiera!' unless fqdn
|
|
fqdn
|
|
end
|
|
|
|
def self.role
|
|
hiera 'role'
|
|
end
|
|
|
|
def self.hostname
|
|
self.fqdn.split('.').first
|
|
end
|
|
|
|
def self.node_hash
|
|
hiera('nodes').find { |node| node['fqdn'] == fqdn } || {}
|
|
end
|
|
|
|
def self.manifest_present?(manifest)
|
|
manifest_path = File.join self.modular_manifests_node_dir, manifest
|
|
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 => fqdn,
|
|
:hostname => hostname,
|
|
:processorcount => '4',
|
|
:memorysize_mb => '32138.66',
|
|
:memorysize => '31.39 GB',
|
|
:kernel => 'Linux',
|
|
:osfamily => 'Debian',
|
|
:operatingsystem => 'Ubuntu',
|
|
:operatingsystemrelease => '14.04',
|
|
:lsbdistid => 'Ubuntu',
|
|
:l3_fqdn_hostname => hostname,
|
|
:l3_default_route => '172.16.1.1',
|
|
:concat_basedir => '/tmp/',
|
|
:l23_os => 'ubuntu',
|
|
}
|
|
end
|
|
|
|
def self.centos_facts
|
|
{
|
|
:fqdn => fqdn,
|
|
:hostname => hostname,
|
|
:processorcount => '4',
|
|
:memorysize_mb => '32138.66',
|
|
:memorysize => '31.39 GB',
|
|
:kernel => 'Linux',
|
|
:osfamily => 'RedHat',
|
|
:operatingsystem => 'CentOS',
|
|
:operatingsystemrelease => '6.5',
|
|
:lsbdistid => 'CentOS',
|
|
:l3_fqdn_hostname => hostname,
|
|
:l3_default_route => '172.16.1.1',
|
|
:concat_basedir => '/tmp/',
|
|
:l23_os => 'centos6',
|
|
}
|
|
end
|
|
|
|
def self.modular_manifests_node_dir
|
|
'/etc/puppet/modules/osnailyfacter/modular'
|
|
end
|
|
|
|
def self.modular_manifests_local_dir
|
|
File.join self.module_path, 'osnailyfacter/modular'
|
|
end
|
|
|
|
def self.manifest=(manifest)
|
|
debug "Set manifest to: #{manifest} -> #{File.join self.modular_manifests_local_dir, 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
|
|
@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['SPEC_SAVE_FILE_RESOURCES'], self.astute_yaml_base
|
|
end
|
|
|
|
def self.file_resources_list_file(manifest, os)
|
|
file_name = manifest.gsub('/', '_').gsub('.pp', '') + "_#{os}_files.yaml"
|
|
File.join file_resources_lists_dir, file_name
|
|
end
|
|
|
|
def self.save_file_resources_list(data, os)
|
|
begin
|
|
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
|
|
rescue
|
|
puts "Could not save File resources list for manifest: '#{manifest}' to: '#{file_path}'"
|
|
else
|
|
puts "File resources list for manifest: '#{manifest}' saved to: '#{file_path}'"
|
|
end
|
|
end
|
|
|
|
## Package resources list ##
|
|
|
|
def self.package_resources_lists_dir
|
|
File.expand_path File.join ENV['SPEC_SAVE_PACKAGE_RESOURCES'], self.astute_yaml_base
|
|
end
|
|
|
|
def self.package_resources_list_file(manifest, os)
|
|
file_name = manifest.gsub('/', '_').gsub('.pp', '') + "_#{os}_packages.yaml"
|
|
File.join package_resources_lists_dir, file_name
|
|
end
|
|
|
|
def self.save_package_resources_list(data, os)
|
|
begin
|
|
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
|
|
rescue
|
|
puts "Could not save Package resources list for manifest '#{manifest}' to '#{file_path}'"
|
|
else
|
|
puts "Package resources list for manifest '#{manifest}' saved to '#{file_path}'"
|
|
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
|
|
|
|
def self.debug(msg)
|
|
puts msg if ENV['SPEC_RSPEC_DEBUG']
|
|
end
|
|
|
|
def self.current_spec(example)
|
|
example_group = lambda do |metdata|
|
|
return example_group.call metdata[:example_group] if metdata[:example_group]
|
|
return example_group.call metdata[:parent_example_group] if metdata[:parent_example_group]
|
|
file_path = metdata[:absolute_file_path]
|
|
return file_path
|
|
end
|
|
example_group.call example.metadata
|
|
end
|
|
|
|
module Utils
|
|
def self.filter_nodes(hash, name, value)
|
|
hash.select do |it|
|
|
it[name] == value
|
|
end
|
|
end
|
|
|
|
def self.nodes_to_hash(hash, name, value)
|
|
result = {}
|
|
hash.each do |element|
|
|
result[element[name]] = element[value]
|
|
end
|
|
result
|
|
end
|
|
|
|
def self.ipsort (ips)
|
|
require 'rubygems'
|
|
require 'ipaddr'
|
|
ips.sort { |a,b| IPAddr.new( a ) <=> IPAddr.new( b ) }
|
|
end
|
|
end
|
|
end
|
|
|
|
# Add fixture lib dirs to LOAD_PATH. Work-around for PUP-3336
|
|
if Puppet.version < '4.0.0'
|
|
Dir["#{Noop.module_path}/*/lib"].entries.each do |lib_dir|
|
|
$LOAD_PATH << lib_dir
|
|
end
|
|
end
|
|
|
|
RSpec.configure do |c|
|
|
c.module_path = Noop.module_path
|
|
c.expose_current_running_example_as :example
|
|
|
|
c.pattern = 'hosts/**'
|
|
|
|
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 Noop.puppet_logs_dir
|
|
Puppet::Util::Log.newdestination(Noop.puppet_log_file)
|
|
Puppet::Util::Log.level = :debug
|
|
end
|
|
end
|
|
|
|
c.after :each do
|
|
# Puppet logs cleanup
|
|
if Noop.puppet_logs_dir
|
|
Puppet::Util::Log.close_all
|
|
# 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
|
|
|
|
c.mock_with :rspec
|
|
|
|
end
|
|
|
|
Noop.hiera_puppet_override
|
|
|