control-repo/Rakefile
2018-12-19 00:12:03 -05:00

210 lines
6.1 KiB
Ruby

require 'fileutils'
require 'puppet-lint/tasks/puppet-lint'
require 'puppetlabs_spec_helper/rake_tasks'
require 'ra10ke'
require 'r10k/puppetfile'
require 'erb'
require 'json'
require 'rest-client'
require 'onceover/rake_tasks'
PuppetSyntax.app_management = true
PuppetSyntax.exclude_paths = ["site/**/plans/*"]
PuppetLint.configuration.fail_on_warnings = true
PuppetLint.configuration.send('relative')
PuppetLint.configuration.send('disable_140chars')
PuppetLint.configuration.send('disable_class_inherits_from_params_class')
PuppetLint.configuration.send('disable_documentation')
PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp", "bundle/**/*", "vendor/**/*"]
Rake::Task[:spec_prep].enhance [:generate_fixtures]
desc "Run tests"
task :run_tests do
print "Executing Lint Test...\n"
Rake::Task[:lint].execute
print " -> Success!\n\n"
print "Executing Syntax Test...\n"
Rake::Task[:syntax].execute
print " -> Success!\n\n"
print "Executing r10k(Puppetfile) Syntax Test...\n -> "
Rake::Task['r10k:syntax'].execute
print "\n"
print "Checking for missing spec tests...\n"
Rake::Task[:check_for_spec_tests].execute
print " -> No missing tests!\n\n"
print "Launching rspec tests...\n"
Rake::Task[:spec].execute
end
desc "Generate Fixtures files for role/profile"
task :generate_fixtures do
print "Generating Fixtures..."
build_fixtures(File.dirname(__FILE__))
print "Done!\n"
end
desc "Generate spec tests for missing classes"
task :generate_spec_tests do
spec_gen(true)
end
desc "Get spec test status"
task :check_for_spec_tests do
spec_gen
end
desc "Show PE Only Modules"
task :pe_only_mods do
puts get_pe_modules
end
def get_pe_modules
# Query Puppet Forge for the latest list of PE-only modules
# Thanks to dan-wittenberg for the original logic on this!
modules = {}
url="https://forgeapi.puppetlabs.com/v3/modules?module_groups=pe_only"
r = RestClient.get url, { :accept => 'application/json', :charset => 'utf-8' }
JSON.parse(r.force_encoding("UTF-8"))['results'].each do |x|
name = x['current_release']['metadata']['name'].gsub('/','-')
modules[name] = "git@github.com:puppetlabs/#{name}.git"
end
modules
end
def spec_gen(create=false)
exit_code = 0
['role','profile'].each do |m|
# For role or profile, find all the classes
classes = Array.new
pattern = 'site/profile/manifests/*/*.pp' if m == 'profile'
pattern = 'site/role/manifests/*/*.pp' if m == 'role'
Dir.glob("#{pattern}").each do |f|
File.open(f).read.each_line do |l|
c = l.scan(/(\s+)?class\s+([a-zA-Z:_]+)\s+[\{,\(]/)
# Add this class to the classes array
classes.push(c[0][1]) if !c.empty?
end
end
# For each class, see if a spec file exists - using naming convention
# <class>_<subclass>[_<subclass>_]_spec.rb
classes.each do |c|
spec_file = "#{File.dirname(__FILE__)}/spec/classes/#{m}/#{c.split('::').join('_')}_spec.rb"
# If no spec file exists, create a blank should compile test file
if File.exists?(spec_file)
puts "Class #{c} - Spec file already exists at #{spec_file}!" if create == true
else
if create == true
puts "Class #{c} - Creating... #{spec_file}!"
File.open(spec_file, 'w') do |f|
f.write evaluate_template('spec_template.rb.erb',binding)
end
else
puts "Class #{c} - Spec file missing!"
exit_code = 1
end
end
end
end
if exit_code != 0
raise(exit_code)
end
end
# Most of this logic was lifted from onceover (comments and all) - thank you!
# https://github.com/dylanratcliffe/onceover/blob/98811bee7bf373e1a22706d98f9ccc1360aff482/lib/onceover/controlrepo.rb
def evaluate_template(template_name,bind)
template_dir = File.expand_path('./scripts',File.dirname(__FILE__))
template = File.read(File.expand_path("./#{template_name}",template_dir))
ERB.new(template, nil, '-').result(bind)
end
def build_fixtures(controlrepo)
# Load up the Puppetfile using R10k
puppetfile = R10K::Puppetfile.new(controlrepo)
fail 'Could not load Puppetfile' unless puppetfile.load
modules = puppetfile.modules
# Store PE Only Mods list
pe_only = get_pe_modules
# Iterate over everything and seperate it out for the sake of readability
symlinks = []
forge_modules = []
repositories = []
modules.each do |mod|
# This logic could probably be cleaned up. A lot.
if mod.is_a? R10K::Module::Forge
if mod.expected_version.is_a?(Hash)
# Set it up as a symlink, because we are using local files in the Puppetfile
symlinks << {
'name' => mod.name,
'dir' => mod.expected_version[:path]
}
elsif mod.expected_version.is_a?(String)
# Verify if this is a PE mod or not
# if it is a PE only module; we need to set it up as a git repo for fixtures b/c of license issues
if pe_only.keys.include?(mod.title.gsub('/','-'))
# Its PE Only
repositories << {
'name' => mod.name,
'repo' => mod.instance_variable_get(:@remote) =~ /\.git/ ? mod.instance_variable_get(:@remote) : pe_only[mod.title],
# ^^ This isn't perfect, as some of the repo names don't match - but its a start
'ref' => mod.expected_version
}
else
# Set it up as a normal forge module
forge_modules << {
'name' => mod.name,
'repo' => mod.title,
'ref' => mod.expected_version
}
end
end
elsif mod.is_a? R10K::Module::Git
# Set it up as a git repo
repositories << {
'name' => mod.name,
'repo' => mod.instance_variable_get(:@remote),
'ref' => mod.version
}
end
end
symlinks << {
'name' => "profile",
'dir' => '"#{source_dir}/site/profile"',
}
symlinks << {
'name' => "role",
'dir' => '"#{source_dir}/site/role"',
}
symlinks << {
'name' => "manifests",
'dir' => '"#{source_dir}/manifests"',
}
File.open("#{File.dirname(__FILE__)}/.fixtures.yml",'w') do |f|
f.write evaluate_template('fixtures.yml.erb',binding)
end
end