Add new framework library

Partial blueprint: deployment-data-dryrun
Change-Id: Ifd81c68e5f08e02ab3c2df2910eab073a743f941
This commit is contained in:
Dmitry Ilyin 2016-02-10 18:28:36 +03:00
parent 8fa5c3c06c
commit c60235736c
38 changed files with 2654 additions and 0 deletions

2
.rspec Normal file
View File

@ -0,0 +1,2 @@
-f doc
--color

24
Gemfile Normal file
View File

@ -0,0 +1,24 @@
source 'https://rubygems.org'
group :development, :test do
gem 'puppetlabs_spec_helper'
gem 'puppet-lint', '~> 0.3.2'
gem 'rspec-puppet', '~> 2.2.0'
gem 'rspec-puppet-utils', '~> 2.0.0'
gem 'openstack'
gem 'netaddr'
gem 'deep_merge'
gem 'pry'
gem 'simplecov'
gem 'puppet-spec'
gem 'colorize'
gem 'parallel'
end
if ENV['PUPPET_GEM_VERSION']
gem 'puppet', ENV['PUPPET_GEM_VERSION']
else
gem 'puppet', '3.4.3'
end
# vim:ft=ruby

0
deployment/.gitkeep Normal file
View File

48
lib/noop.rb Normal file
View File

@ -0,0 +1,48 @@
require_relative 'noop/utils'
require_relative 'noop/config'
require_relative 'noop/manager'
require_relative 'noop/task'
require_relative 'noop/matchers'
module Noop
def self.new_task(*args)
self.task = Noop::Task.new *args
end
def self.task_spec=(value)
self.task.file_name_spec = value
end
def self.task_hiera=(value)
self.task.file_name_hiera = value
end
def self.task_facts=(value)
self.task.file_name_facts = value
end
def self.task_spec
self.task.file_name_spec
end
def self.task_hiera
self.task.file_name_hiera
end
def self.task_facts
self.task.file_name_facts
end
def self.task=(value)
@task = value
end
def self.task
return @task if @task
@task = Noop::Task.new
end
def self.method_missing(method, *args)
self.task.send method, *args
end
end

6
lib/noop/config.rb Normal file
View File

@ -0,0 +1,6 @@
require_relative 'utils'
require_relative 'config/base'
require_relative 'config/hiera'
require_relative 'config/facts'
require_relative 'config/globals'
require_relative 'config/log'

106
lib/noop/config/base.rb Normal file
View File

@ -0,0 +1,106 @@
require 'pathname'
module Noop
module Config
# @return [Pathname]
def self.dir_path_config
return @dirname if @dirname
@dirname = Pathname.new(__FILE__).dirname.realpath
end
# @return [Pathname]
def self.dir_path_root
return @dir_path_root if @dir_path_root
@dir_path_root = Noop::Utils.path_from_env 'SPEC_ROOT_DIR'
@dir_path_root = dir_path_config.parent.parent.parent unless @dir_path_root
begin
@dir_path_root = @dir_path_root.realpath
rescue
@dir_path_root
end
end
# @return [Pathname]
def self.dir_path_task_spec
return @dir_path_task_spec if @dir_path_task_spec
@dir_path_task_spec = Noop::Utils.path_from_env 'SPEC_SPEC_DIR'
@dir_path_task_spec = dir_path_root + 'spec' + 'hosts' unless @dir_path_task_spec
begin
@dir_path_task_spec = @dir_path_task_spec.realpath
rescue
@dir_path_task_spec
end
end
# @return [Pathname]
def self.dir_path_modules_local
return @dir_path_modules_local if @dir_path_modules_local
@dir_path_modules_local = Noop::Utils.path_from_env 'SPEC_MODULEPATH', 'SPEC_MODULE_PATH'
@dir_path_modules_local = dir_path_root + 'modules' unless @dir_path_modules_local
begin
@dir_path_modules_local = @dir_path_modules_local.realpath
rescue
@dir_path_modules_local
end
end
# @return [Pathname]
def self.dir_path_tasks_local
return @dir_path_tasks_local if @dir_path_tasks_local
@dir_path_tasks_local = Noop::Utils.path_from_env 'SPEC_TASK_DIR'
@dir_path_tasks_local = dir_path_root + 'tasks' unless @dir_path_tasks_local
begin
@dir_path_tasks_local = @dir_path_tasks_local.realpath
rescue
@dir_path_tasks_local
end
end
# @return [Pathname]
def self.dir_path_modules_node
return @dir_path_modules_node if @dir_path_modules_node
@dir_path_modules_node = Pathname.new '/etc/puppet/modules'
end
# @return [Pathname]
def self.dir_path_tasks_node
return @dir_path_tasks_node if @dir_path_tasks_node
@dir_path_tasks_node = dir_path_modules_node + 'osnailyfacter' + 'modular'
end
# @return [Pathname]
def self.dir_path_deployment
return @dir_path_deployment if @dir_path_deployment
@dir_path_deployment = Noop::Utils.path_from_env 'SPEC_DEPLOYMENT_DIR'
@dir_path_deployment = dir_path_root + 'deployment' unless @dir_path_deployment
begin
@dir_path_deployment = @dir_path_deployment.realpath
rescue
@dir_path_deployment
end
end
# Workspace directory where gem bundle will be created
# is passed from Jenkins or the default value is used
# @return [Pathname]
def self.dir_path_workspace
return @dir_path_workspace if @dir_path_workspace
@dir_path_workspace = Noop::Utils.path_from_env 'WORKSPACE'
@dir_path_workspace = Noop::Config.dir_path_root + Pathname.new('workspace') unless @dir_path_workspace
begin
@dir_path_workspace = @dir_path_workspace.realpath
rescue
nil
end
@dir_path_workspace.mkpath
raise "Workspace '#{@dir_path_workspace}' is not a directory!" unless @dir_path_workspace.directory?
@dir_path_workspace
end
# @return [Pathname]
def self.dir_path_reports
return @dir_path_reports if @dir_path_reports
@dir_path_reports = dir_path_root + 'reports'
end
end
end

36
lib/noop/config/facts.rb Normal file
View File

@ -0,0 +1,36 @@
require 'pathname'
module Noop
module Config
# @return [Pathname]
def self.dir_name_facts
Pathname.new 'facts'
end
# @return [Pathname]
def self.dir_path_facts
return @dir_path_facts if @dir_path_facts
@dir_path_facts = Noop::Utils.path_from_env 'SPEC_FACTS_DIR'
@dir_path_facts = dir_path_root + dir_name_facts unless @dir_path_facts
begin
@dir_path_facts = @dir_path_facts.realpath
rescue
@dir_path_facts
end
end
# @return [Pathname]
def self.dir_name_facts_override
Pathname.new 'override'
end
# @return [Pathname]
def self.dir_path_facts_override
dir_path_facts + dir_name_facts_override
end
def self.default_facts_file_name
Pathname.new 'ubuntu.yaml'
end
end
end

View File

@ -0,0 +1,33 @@
require 'pathname'
module Noop
module Config
# @return [Pathname]
def self.spec_name_globals
Pathname.new 'globals/globals_spec.rb'
end
# @return [Pathname]
def self.spec_path_globals
dir_path_task_spec + spec_name_globals
end
def self.manifest_name_globals
Noop::Utils.convert_to_manifest spec_name_globals
end
def self.manifest_path_globals
dir_path_tasks_local + manifest_name_globals
end
# @return [Pathname]
def self.dir_name_globals
Pathname.new 'globals'
end
# @return [Pathname]
def self.dir_path_globals
dir_path_hiera + dir_name_globals
end
end
end

36
lib/noop/config/hiera.rb Normal file
View File

@ -0,0 +1,36 @@
require 'pathname'
module Noop
module Config
# @return [Pathname]
def self.dir_name_hiera
Pathname.new 'hiera'
end
# @return [Pathname]
def self.dir_path_hiera
return @dir_path_hiera if @dir_path_hiera
@dir_path_hiera = Noop::Utils.path_from_env 'SPEC_HIERA_DIR', 'SPEC_YAML_DIR'
@dir_path_hiera = dir_path_root + dir_name_hiera unless @dir_path_hiera
begin
@dir_path_hiera = @dir_path_hiera.realpath
rescue
@dir_path_hiera
end
end
# @return [Pathname]
def self.dir_name_hiera_override
Pathname.new 'override'
end
# @return [Pathname]
def self.dir_path_hiera_override
dir_path_hiera + dir_name_hiera_override
end
def self.default_hiera_file_name
Pathname.new 'novanet-primary-controller.yaml'
end
end
end

26
lib/noop/config/log.rb Normal file
View File

@ -0,0 +1,26 @@
require 'logger'
module Noop
module Config
def self.log_destination
return ENV['SPEC_DEBUG_LOG'] if ENV['SPEC_DEBUG_LOG']
STDOUT
end
def self.log_level
if ENV['SPEC_TASK_DEBUG']
Logger::DEBUG
else
Logger::WARN
end
end
def self.log
return @log if @log
@log = Logger.new log_destination
@log.level = log_level
@log.progname = 'noop_manager'
@log
end
end
end

7
lib/noop/manager.rb Normal file
View File

@ -0,0 +1,7 @@
require_relative 'config'
require_relative 'manager/library'
require_relative 'manager/options'
require_relative 'manager/actions'
require_relative 'manager/report'
require_relative 'manager/setup'
require_relative 'manager/xunit'

153
lib/noop/manager/actions.rb Normal file
View File

@ -0,0 +1,153 @@
require 'parallel'
module Noop
class Manager
def find_tasks_without_specs
task_file_names.reject do |manifest|
spec = Noop::Utils.convert_to_spec manifest
spec_file_names.include? spec
end
end
def debug(message)
Noop::Config.log.debug message
end
def output(message)
puts message
end
def parallel_run?
options[:parallel_run] and options[:parallel_run] > 0
end
def list_hiera_files
hiera_file_names.sort.each do |file_name_hiera|
next unless hiera_included? file_name_hiera
output file_name_hiera
end
exit(0)
end
def list_facts_files
facts_file_names.sort.each do |file_name_facts|
next unless facts_included? file_name_facts
output file_name_facts
end
exit(0)
end
def list_spec_files
spec_file_names.sort.each do |file_name_spec|
next unless spec_included? file_name_spec
output file_name_spec
end
exit(0)
end
def list_task_files
task_file_names.sort.each do |file_name_task|
output file_name_task
end
exit(0)
end
def run_all_tasks
Parallel.map(task_list, :in_threads => options[:parallel_run]) do |task|
task.run unless options[:pretend]
task
end
end
def run_failed_tasks
Parallel.map(task_list, :in_threads => options[:parallel_run]) do |task|
next if task.success?
task.status = :pending
task.run unless options[:pretend]
task
end
end
def load_task_reports
Parallel.map(task_list, :in_threads => options[:parallel_run]) do |task|
task.file_load_report_json
task.determine_task_status
task
end
end
def list_tasks_without_specs
tasks_without_specs = find_tasks_without_specs.to_a
if tasks_without_specs.any?
Noop::Utils.error "There are tasks without specs: #{tasks_without_specs.join ', '}"
end
end
def have_failed_tasks?
task_list.any? do |task|
task.failed?
end
end
def exit_with_error_code
exit 1 if have_failed_tasks?
exit 0
end
def main
options
if ENV['SPEC_TASK_CONSOLE']
require 'pry'
binding.pry
exit(0)
end
if options[:list_missing]
list_tasks_without_specs
end
if options[:bundle_setup]
setup_bundle
end
if options[:update_librarian_puppet]
prepare_library
end
if options[:self_check]
check_paths
show_filters
show_library
exit(0)
end
list_hiera_files if options[:list_hiera]
list_facts_files if options[:list_facts]
list_spec_files if options[:list_specs]
list_task_files if options[:list_tasks]
if options[:run_failed_tasks]
load_task_reports
run_failed_tasks
task_report
exit_with_error_code
end
if options[:load_saved_reports]
load_task_reports
task_report
save_xunit_report if options[:xunit_report]
exit_with_error_code
end
run_all_tasks
task_report
save_xunit_report if options[:xunit_report]
exit_with_error_code
end
end
end

283
lib/noop/manager/library.rb Normal file
View File

@ -0,0 +1,283 @@
require 'yaml'
require 'set'
module Noop
class Manager
# @return [Array<Pathname>]
def spec_file_names
return @spec_file_names if @spec_file_names
@spec_file_names = []
Noop::Utils.error "No #{Noop::Config.dir_path_task_spec} directory!" unless Noop::Config.dir_path_task_spec.directory?
Noop::Config.dir_path_task_spec.find do |spec_file|
next unless spec_file.file?
next unless spec_file.to_s.end_with? '_spec.rb'
@spec_file_names << spec_file.relative_path_from(Noop::Config.dir_path_task_spec)
end
@spec_file_names
end
# @return [Array<Pathname>]
def hiera_file_names
return @hiera_file_names if @hiera_file_names
@hiera_file_names = []
Noop::Utils.error "No #{Noop::Config.dir_path_hiera} directory!" unless Noop::Config.dir_path_hiera.directory?
Noop::Config.dir_path_hiera.find do |hiera_name|
next unless hiera_name.file?
next unless hiera_name.to_s.end_with? '.yaml'
base_dir = hiera_name.dirname.basename
next if base_dir == Noop::Config.dir_name_hiera_override
next if base_dir == Noop::Config.dir_name_globals
@hiera_file_names << hiera_name.relative_path_from(Noop::Config.dir_path_hiera)
end
@hiera_file_names
end
# @return [Array<Pathname>]
def facts_file_names
return @facts_file_names if @facts_file_names
@facts_file_names = []
Noop::Utils.error "No #{Noop::Config.dir_path_facts} directory!" unless Noop::Config.dir_path_facts.directory?
Noop::Config.dir_path_facts.find do |facts_name|
next unless facts_name.file?
next unless facts_name.to_s.end_with? '.yaml'
next if facts_name.dirname.basename == Noop::Config.dir_name_facts_override
@facts_file_names << facts_name.relative_path_from(Noop::Config.dir_path_facts)
end
@facts_file_names
end
# @return [Array<Pathname>]
def task_file_names
return @task_file_names if @task_file_names
@task_file_names = []
Noop::Utils.error "No #{Noop::Config.dir_path_tasks_local} directory!" unless Noop::Config.dir_path_tasks_local.directory?
Noop::Config.dir_path_tasks_local.find do |task_name|
next unless task_name.file?
next unless task_name.to_s.end_with? '.pp'
@task_file_names << task_name.relative_path_from(Noop::Config.dir_path_tasks_local)
end
@task_file_names
end
# @return [Hash<String => Hash>]
def task_graph_metadata
return @task_graph_metadata if @task_graph_metadata
@task_graph_metadata = {}
Noop::Utils.error "No #{Noop::Config.dir_path_modules_local} directory!" unless Noop::Config.dir_path_modules_local.directory?
Noop::Config.dir_path_modules_local.find do |task_file|
next unless task_file.file?
next unless task_file.to_s.end_with? 'tasks.yaml'
begin
tasks = YAML.load_file task_file
rescue
next
end
tasks.each do |task|
id = task['id']
@task_graph_metadata[id] = task
end
end
@task_graph_metadata.each do |id, group_task|
next unless group_task['type'] == 'group' and group_task['tasks'].is_a? Array
group_task['tasks'].each do |task|
next unless @task_graph_metadata[task]
@task_graph_metadata[task]['groups'] = [] unless @task_graph_metadata[task]['groups'].is_a? Array
@task_graph_metadata[task]['groups'] << id
end
end
@task_graph_metadata
end
# @return [Hash<Pathname => Set>]
def assign_spec_to_roles
return @assign_spec_to_roles if @assign_spec_to_roles
@assign_spec_to_roles = {}
task_graph_metadata.values.each do |task_data|
roles = task_data['groups'] or task_data['roles']
next unless roles.is_a? Array
file_path_manifest = task_data.fetch('parameters', {}).fetch('puppet_manifest', nil)
next unless file_path_manifest
file_path_manifest = Pathname.new file_path_manifest
file_name_manifest = file_path_manifest.relative_path_from Noop::Config.dir_path_tasks_node
file_name_spec = Noop::Utils.convert_to_spec file_name_manifest
roles = Set.new roles
@assign_spec_to_roles[file_name_spec] = Set.new unless @assign_spec_to_roles[file_name_spec].is_a? Set
@assign_spec_to_roles[file_name_spec] += roles
end
@assign_spec_to_roles
end
# @return [Hash<Pathname => Set>]
def assign_hiera_to_roles
return @assign_hiera_to_roles if @assign_hiera_to_roles
@assign_hiera_to_roles = {}
hiera_file_names.each do |hiera_file|
begin
data = YAML.load_file(Noop::Config.dir_path_hiera + hiera_file)
next unless data.is_a? Hash
fqdn = data['fqdn']
next unless fqdn
nodes = data.fetch('network_metadata', {}).fetch('nodes', nil)
next unless nodes
this_node = nodes.find do |node|
node.last['fqdn'] == fqdn
end
node_roles = this_node.last['node_roles']
roles = Set.new
roles.merge node_roles if node_roles.is_a? Array
role = data['role']
roles.add role if role
@assign_hiera_to_roles[hiera_file] = roles
rescue
next
end
end
@assign_hiera_to_roles
end
def assign_spec_to_hiera
return @assign_spec_to_hiera if @assign_spec_to_hiera
@assign_spec_to_hiera = {}
assign_spec_to_roles.each do |file_name_spec, spec_roles|
hiera_files = assign_hiera_to_roles.select do |file_name_hiera, hiera_roles|
hiera_roles.intersect? spec_roles
end.keys
@assign_spec_to_hiera[file_name_spec] = hiera_files if hiera_files.any?
end
@assign_spec_to_hiera
end
# @return [Hash<Pathname => Array>]
def spec_run_metadata
return @spec_run_metadata if @spec_run_metadata
@spec_run_metadata = {}
Noop::Config.dir_path_task_spec.find do |spec_file|
next unless spec_file.file?
next unless spec_file.to_s.end_with? '_spec.rb'
spec_name = spec_file.relative_path_from(Noop::Config.dir_path_task_spec)
spec_data = parse_spec_file spec_file
@spec_run_metadata[spec_name] = spec_data if spec_data.any?
end
@spec_run_metadata
end
# @param [Pathname] task_spec
def parse_spec_file(task_spec)
task_spec_metadata = {}
begin
text = task_spec.read
text.split("\n").each do |line|
line = line.downcase
if line =~ /^\s*#\s*(?:yamls|hiera):\s*(.*)/
task_spec_metadata[:hiera] = get_list_of_yamls $1
end
if line =~ /^\s*#\s*facts:\s*(.*)/
task_spec_metadata[:facts] = get_list_of_yamls $1
end
if line =~ /disable_spec/
task_spec_metadata[:disable] = true
end
if line =~ /^\s*#\s*run:\s*(.*)/
run_record = get_list_of_yamls $1
if run_record.length >= 2
run_record = {
:hiera => run_record[0],
:facts => run_record[1],
}
task_spec_metadata[:runs] = [] unless task_spec_metadata[:runs].is_a? Array
task_spec_metadata[:runs] << run_record
end
end
end
rescue
return task_spec_metadata
end
task_spec_metadata
end
# @return [Array<Pathname>]
def get_list_of_yamls(line)
line = line.split /\s*,\s*|\s+/
line.map do |yaml|
yaml = Pathname.new yaml
yaml = yaml.sub /$/, '.yaml' unless yaml.extname =~ /\.yaml/i
yaml
end
end
def get_spec_runs(file_name_spec)
file_name_spec = Noop::Utils.convert_to_path file_name_spec
metadata = spec_run_metadata.fetch file_name_spec, {}
metadata[:facts] = [Noop::Config.default_facts_file_name] unless metadata[:facts]
metadata[:hiera] = assign_spec_to_hiera.fetch file_name_spec, [] unless metadata[:hiera]
runs = []
metadata[:facts].product metadata[:hiera] do |facts, hiera|
run_record = {
:hiera => hiera,
:facts => facts,
}
runs << run_record
end
runs += metadata[:runs] if metadata[:runs].is_a? Array
runs
end
def spec_included?(spec)
filter = options[:filter_specs]
return true unless filter
filter = [filter] unless filter.is_a? Array
filter.include? spec
end
def facts_included?(facts)
filter = options[:filter_facts]
return true unless filter
filter = [filter] unless filter.is_a? Array
filter.include? facts
end
def hiera_included?(hiera)
filter = options[:filter_hiera]
return true unless filter
filter = [filter] unless filter.is_a? Array
filter.include? hiera
end
def skip_globals?(file_name_spec)
return false unless file_name_spec == Noop::Config.spec_name_globals
return true unless options[:filter_specs]
not spec_included? file_name_spec
end
def spec_is_disabled?(file_name_spec)
file_name_spec = Noop::Utils.convert_to_path file_name_spec
spec_run_metadata.fetch(file_name_spec, {}).fetch(:disable, false)
end
def task_list
return @task_list if @task_list
@task_list = []
spec_file_names.each do |file_name_spec|
next if spec_is_disabled? file_name_spec
next if skip_globals? file_name_spec
next unless spec_included? file_name_spec
get_spec_runs(file_name_spec).each do |run|
next unless run[:hiera] and run[:facts]
next unless facts_included? run[:facts]
next unless hiera_included? run[:hiera]
task = Noop::Task.new file_name_spec, run[:hiera], run[:facts]
task.parallel = true if parallel_run?
@task_list << task
end
end
@task_list
end
end
end

170
lib/noop/manager/options.rb Normal file
View File

@ -0,0 +1,170 @@
require 'optparse'
module Noop
class Manager
def options
return @options if @options
@options = {}
options_defaults @options
optparse = OptionParser.new do |opts|
opts.separator 'Main options:'
opts.on('-j', '--jobs JOBS', 'Parallel run RSpec jobs') do |jobs|
@options[:parallel_run] = jobs.to_i
end
opts.on('-g', '--globals', 'Run all globals tasks and update saved globals YAML files') do |jobs|
ENV['SPEC_UPDATE_GLOBALS'] = 'YES'
options[:filter_specs] = [Noop::Config.spec_name_globals]
end
opts.on('-b', '--bundle_setup', 'Setup Ruby environment using Bundle') do
@options[:bundle_setup] = true
end
opts.on('-B', '--bundle_exec', 'Use "bundle exec" to run rspec') do
ENV['SPEC_BUNDLE_EXEC'] = 'YES'
end
opts.on('-l', '--update-librarian', 'Run librarian-puppet update in the deployment directory prior to testing') do
@options[:update_librarian_puppet] = true
end
opts.on('-L', '--reset-librarian', 'Reset puppet modules to librarian versions in the deployment directory prior to testing') do
@options[:reset_librarian_puppet] = true
end
opts.on('-o', '--report_only_failed', 'Show only failed tasks and examples in the report') do
@options[:report_only_failed] = true
end
opts.on('-r', '--load_saved_reports', 'Read saved report JSON files from the previous run and show tasks report') do
@options[:load_saved_reports] = true
end
opts.on('-R', '--run_failed_tasks', 'Run the task that have previously failed again') do
@options[:run_failed_tasks] = true
end
opts.on('-M', '--list_missing', 'List all task manifests without a spec file') do
@options[:list_missing] = true
end
opts.on('-x', '--xunit_report', 'Save report in xUnit format to a file') do
@options[:xunit_report] = true
end
opts.separator 'List options:'
opts.on('-Y', '--list_hiera', 'List all hiera yaml files') do
@options[:list_hiera] = true
end
opts.on('-S', '--list_specs', 'List all task spec files') do
@options[:list_specs] = true
end
opts.on('-F', '--list_facts', 'List all facts yaml files') do
@options[:list_facts] = true
end
opts.on('-T', '--list_tasks', 'List all task manifest files') do
@options[:list_tasks] = true
end
opts.separator 'Filter options:'
opts.on('-s', '--specs SPEC1,SPEC2', Array, 'Run only these spec files. Example: "hosts/hosts_spec.rb,apache/apache_spec.rb"') do |specs|
@options[:filter_specs] = import_specs_list specs
end
opts.on('-y', '--yamls YAML1,YAML2', Array, 'Run only these hiera yamls. Example: "controller.yaml,compute.yaml"') do |yamls|
@options[:filter_hiera] = import_yamls_list yamls
end
opts.on('-f', '--facts FACTS1,FACTS2', Array, 'Run only these facts yamls. Example: "ubuntu.yaml,centos.yaml"') do |yamls|
@options[:filter_facts] = import_yamls_list yamls
end
# opts.on('-e', '--examples STR1,STR2', Array, 'Run only these spec examples. Example: "should compile"') do |examples|
# @options[:filter_examples] = examples
# end
opts.separator 'Debug options:'
opts.on('-c', '--task_console', 'Run PRY console') do
ENV['SPEC_TASK_CONSOLE'] = 'YES'
end
opts.on('-C', '--rspec_console', 'Run PRY console in the ') do
ENV['SPEC_RSPEC_CONSOLE'] = 'YES'
end
opts.on('-d', '--task_debug', 'Show framework debug messages') do
ENV['SPEC_TASK_DEBUG'] = 'YES'
end
opts.on('-D', '--puppet_debug', 'Show Puppet debug messages') do
ENV['SPEC_PUPPET_DEBUG'] = 'YES'
end
opts.on('--debug_log FILE', 'Write all debug messages to this files') do |file|
ENV['SPEC_DEBUG_LOG'] = file
end
opts.on('-t', '--self-check', 'Perform self-check and diagnostic procedures') do
@options[:self_check] = true
end
opts.on('-p', '--pretend', 'Show which tasks will be run without actually running them') do
@options[:pretend] = true
end
opts.separator 'Path options:'
opts.on('--dir_root DIR', 'Path to the test root folder') do |dir|
ENV['SPEC_ROOT_DIR'] = dir
end
opts.on('--dir_deployment DIR', 'Path to the test deployment folder') do |dir|
ENV['SPEC_DEPLOYMENT_DIR'] = dir
end
opts.on('--dir_hiera_yamls DIR', 'Path to the folder with hiera files') do |dir|
ENV['SPEC_HIERA_DIR'] = dir
end
opts.on('--dir_facts_yamls DIR', 'Path to the folder with facts yaml files') do |dir|
ENV['SPEC_FACTS_DIR'] = dir
end
opts.on('--dir_spec_files DIR', 'Path to the folder with task spec files (changing this may break puppet-rspec)') do |dir|
ENV['SPEC_SPEC_DIR'] = dir
end
opts.on('--dir_task_files DIR', 'Path to the folder with task manifest files') do |dir|
ENV['SPEC_TASK_DIR'] = dir
end
opts.on('--dir_puppet_modules DIR', 'Path to the puppet modules') do |dir|
ENV['SPEC_MODULE_PATH'] = dir
end
opts.separator 'Spec options:'
opts.on('-A', '--catalog_show', 'Show catalog content debug output') do
ENV['SPEC_CATALOG_SHOW'] = 'YES'
end
# opts.on('--catalog_save', 'Save catalog to the files instead of comparing them with the current catalogs') do
# ENV['SPEC_CATALOG_CHECK'] = 'save'
# end
# opts.on('--catalog_check', 'Check the saved catalog against the current one') do
# ENV['SPEC_CATALOG_CHECK'] = 'check'
# end
# opts.on('--spec_generate', 'Generate specs for catalogs') do
# ENV['SPEC_SPEC_GENERATE'] = 'YES'
# end
opts.on('-a', '--spec_status', 'Show spec status blocks') do
ENV['SPEC_SHOW_STATUS'] = 'YES'
end
# opts.on('--spec_coverage', 'Show spec coverage statistics') do
# ENV['SPEC_COVERAGE'] = 'YES'
# end
# opts.on('--puppet_binary_files', 'Check if Puppet installs binary files') do
# ENV['SPEC_PUPPET_BINARY_FILES'] = 'YES'
# end
# opts.on('--file_resources DIR', 'Save file resources to this dir') do |dir|
# ENV['SPEC_SAVE_FILE_RESOURCES'] = dir
# end
end
optparse.parse!
@options
end
def import_specs_list(specs)
specs.map do |spec|
Noop::Utils.convert_to_spec spec
end
end
def import_yamls_list(yamls)
yamls.map do |yaml|
Noop::Utils.convert_to_yaml yaml
end
end
def options_defaults(options)
options[:parallel_run] = 0
end
end
end

196
lib/noop/manager/report.rb Normal file
View File

@ -0,0 +1,196 @@
require 'erb'
require 'colorize'
require 'rexml/document'
module Noop
class Manager
STATUS_STRING_LENGTH = 8
def tasks_report_structure(tasks)
tasks_report = []
tasks.each do |task|
task_hash = {}
task_hash[:status] = task.status
task_hash[:name] = task.to_s
task_hash[:description] = task.description
task_hash[:spec] = task.file_name_spec.to_s
task_hash[:hiera] = task.file_name_hiera.to_s
task_hash[:facts] = task.file_name_facts.to_s
task_hash[:task] = task.file_name_manifest.to_s
task_hash[:examples] = []
if task.report.is_a? Hash
examples = task.report['examples']
next unless examples.is_a? Array
examples.each do |example|
example_hash = {}
example_hash[:file_path] = example['file_path']
example_hash[:line_number] = example['line_number']
example_hash[:description] = example['description']
example_hash[:status] = example['status']
example_hash[:run_time] = example['run_time']
example_hash[:pending_message] = example['pending_message']
exception_class = example.fetch('exception', {}).fetch('class', nil)
exception_message = example.fetch('exception', {}).fetch('message', nil)
next unless example_hash[:description] and example_hash[:status]
if exception_class and exception_message
example_hash[:exception_class] = exception_class
example_hash[:exception_message] = exception_message
end
task_hash[:examples] << example_hash
end
summary = task.report['summary']
task_hash[:example_count] = summary['example_count']
task_hash[:failure_count] = summary['failure_count']
task_hash[:pending_count] = summary['pending_count']
task_hash[:duration] = summary['duration']
end
tasks_report << task_hash
end
tasks_report
end
def output_task_status(task)
return if options[:report_only_failed] and task.success?
line = task_status_string task
line += "#{task.file_base_spec.to_s.ljust max_length_spec + 1}"
line += "#{task.file_base_facts.to_s.ljust max_length_facts + 1}"
line += "#{task.file_base_hiera.to_s.ljust max_length_hiera + 1}"
output line
output_task_examples task
end
def output_task_examples(task)
return unless task.report.is_a? Hash
examples = task.report['examples']
return unless examples.is_a? Array
examples.each do |example|
description = example['description']
status = example['status']
next unless description and status
next if options[:report_only_failed] and status == 'passed'
line = " #{example_status_string status} #{description}"
exception_message = example.fetch('exception', {}).fetch('message', nil)
line += " (#{exception_message.colorize :cyan})" if exception_message
output line
end
end
def task_status_string(task)
if task.pending?
'PENDING'.ljust(STATUS_STRING_LENGTH).colorize :blue
elsif task.success?
'SUCCESS'.ljust(STATUS_STRING_LENGTH).colorize :green
elsif task.failed?
'FAILED'.ljust(STATUS_STRING_LENGTH).colorize :red
else
task.status
end
end
def example_status_string(status)
if status == 'passed'
status.ljust(STATUS_STRING_LENGTH).colorize :green
elsif status == 'failed'
status.ljust(STATUS_STRING_LENGTH).colorize :red
else
status.ljust(STATUS_STRING_LENGTH).colorize :blue
end
end
def directory_check_status_string(directory)
if directory.directory?
'SUCCESS'.ljust(STATUS_STRING_LENGTH).colorize :green
else
'FAILED'.ljust(STATUS_STRING_LENGTH).colorize :red
end
end
def max_length_spec
return @max_length_spec if @max_length_spec
@max_length_spec = task_list.map do |task|
task.file_base_spec.to_s.length
end.max
end
def max_length_hiera
return @max_length_hiera if @max_length_hiera
@max_length_hiera = task_list.map do |task|
task.file_base_hiera.to_s.length
end.max
end
def max_length_facts
return @max_length_facts if @max_length_facts
@max_length_facts = task_list.map do |task|
task.file_base_facts.to_s.length
end.max
end
def task_report
task_list.each do |task|
output_task_status task
end
end
def show_filters
if options[:filter_specs]
options[:filter_specs] = [options[:filter_specs]] unless options[:filter_specs].is_a? Array
output "Spec filter: #{options[:filter_specs].join ', '}"
end
if options[:filter_facts]
options[:filter_facts] = [options[:filter_facts]] unless options[:filter_facts].is_a? Array
output "Facts filter: #{options[:filter_facts].join ', '}"
end
if options[:filter_hiera]
options[:filter_hiera] = [options[:filter_hiera]] unless options[:filter_hiera].is_a? Array
output "Hiera filter: #{options[:filter_hiera].join ', '}"
end
if options[:filter_examples]
options[:filter_examples] = [options[:filter_examples]] unless options[:filter_examples].is_a? Array
output "Examples filter: #{options[:filter_examples].join ', '}"
end
end
def show_library
template = <<-'eof'
<%= '=' * 80 %>
Tasks discovered: <%= task_file_names.length %>
Specs discovered: <%= spec_file_names.length %>
Hiera discovered: <%= hiera_file_names.length %>
Facts discovered: <%= facts_file_names.length %>
Tasks in graph metadata: <%= task_graph_metadata.length %>
Tasks with spec metadata: <%= spec_run_metadata.length %>
Total tasks to run: <%= task_list.count %>
eof
output ERB.new(template, nil, '-').result(binding)
end
def check_paths
paths = [
:dir_path_config,
:dir_path_root,
:dir_path_task_spec,
:dir_path_modules_local,
:dir_path_tasks_local,
:dir_path_deployment,
:dir_path_workspace,
:dir_path_hiera,
:dir_path_hiera_override,
:dir_path_facts,
:dir_path_facts_override,
:dir_path_globals,
:dir_path_reports,
]
max_length = paths.map { |p| p.to_s.length }.max
paths.each do |path|
directory = Noop::Config.send path
output "#{directory_check_status_string directory} #{path.to_s.ljust max_length} #{directory}"
end
end
end
end

46
lib/noop/manager/setup.rb Normal file
View File

@ -0,0 +1,46 @@
module Noop
class Manager
PUPPET_GEM_VERSION = '~> 3.8.0'
def dir_path_gem_home
return Pathname.new ENV['GEM_HOME'] if ENV['GEM_HOME']
dir_name_bundle = Pathname.new '.bundled_gems'
Noop::Utils.dir_path_workspace + dir_name_bundle
end
def bundle_installed?
`bundle --version`
$?.exitstatus == 0
end
def setup_bundle
Noop::Utils.error 'Bundle is not installed!' unless bundle_installed?
ENV['GEM_HOME'] = dir_path_gem_home.to_s
ENV['PUPPET_GEM_VERSION'] = PUPPET_GEM_VERSION unless ENV['PUPPET_GEM_VERSION']
Dir.chdir Noop::Config.dir_path_root
Noop::Utils.run 'bundle install'
Noop::Utils.run 'bundle update'
Noop::Utils.error 'Could not prepare bundle environment!' if $?.exitstatus != 0
end
# run librarian-puppet to fetch modules as necessary
def prepare_library
# these are needed to ensure we have the correctly bundle
ENV['PUPPET_GEM_VERSION'] = PUPPET_GEM_VERSION unless ENV['PUPPET_GEM_VERSION']
ENV['BUNDLE_DIR'] = dir_path_gem_home.to_s
ENV['GEM_HOME'] = dir_path_gem_home.to_s
command = './update_modules.sh -v'
# pass the bundle parameter to update_modules if specified for this script
command = command + ' -b' if options[:bundle_exec]
# pass the reset parameter to update_modules if specified for this script
command = command + ' -r' if options[:reset_librarian_puppet]
Noop::Utils.debug 'Starting update_modules script'
Dir.chdir Noop::Config.dir_path_deployment
Noop::Utils.run command
Noop::Utils.error 'Unable to update upstream puppet modules using librarian-puppet!' if $?.exitstatus != 0
Noop::Utils.debug 'Finished update_modules script'
end
end
end

86
lib/noop/manager/xunit.rb Normal file
View File

@ -0,0 +1,86 @@
module Noop
class Manager
def xunit_report(tasks)
tasks_report = tasks_report_structure tasks
return unless tasks_report.is_a? Array
document = REXML::Document.new
declaration = REXML::XMLDecl.new
declaration.encoding = 'UTF-8'
declaration.version = '1.0'
document.add declaration
testsuites = document.add_element 'testsuites'
tests = 0
failures = 0
task_id = 0
tasks_report.each do |task|
testsuite = testsuites.add_element 'testsuite'
testsuite.add_attribute 'id', task_id
task_id += 1
testsuite.add_attribute 'name', task[:description]
testsuite.add_attribute 'package', task[:name]
testsuite.add_attribute 'tests', task[:example_count]
testsuite.add_attribute 'failures', task[:failure_count]
testsuite.add_attribute 'skipped', task[:pending_count]
testsuite.add_attribute 'time', task[:duration]
testsuite.add_attribute 'status', task[:status]
properties = testsuite.add_element 'properties'
property_task = properties.add_element 'property'
property_task.add_attribute 'name', 'task'
property_task.add_attribute 'value', task[:task]
property_spec = properties.add_element 'property'
property_spec.add_attribute 'name', 'spec'
property_spec.add_attribute 'value', task[:spec]
property_hiera = properties.add_element 'property'
property_hiera.add_attribute 'name', 'hiera'
property_hiera.add_attribute 'value', task[:hiera]
property_facts = properties.add_element 'property'
property_facts.add_attribute 'name', 'facts'
property_facts.add_attribute 'value', task[:facts]
if task[:examples].is_a? Array
task[:examples].each do |example|
tests += 1
testcase = testsuite.add_element 'testcase'
testcase.add_attribute 'name', example[:description]
testcase.add_attribute 'classname', "#{example[:file_path]}:#{example[:line_number]}"
testcase.add_attribute 'time', example[:run_time]
testcase.add_attribute 'status', example[:status]
if example[:status] == 'pending'
skipped = testcase.add_element 'skipped'
skipped.add_attribute 'message', example[:pending_message] if example[:pending_message]
end
if example[:status] == 'failed'
failures += 1
end
if example[:exception_message] and example[:exception_class]
failure = testcase.add_element 'failure'
failure.add_attribute 'message', example[:exception_message]
failure.add_attribute 'type', example[:exception_class]
end
end
end
end
testsuites.add_attribute 'tests', tests
testsuites.add_attribute 'failures', failures
document.to_s
end
def file_name_xunit_report
Pathname.new 'report.xml'
end
def file_path_xunit_report
Noop::Config.dir_path_reports + file_name_xunit_report
end
def save_xunit_report
File.open(file_path_xunit_report.to_s, 'w') do |file|
file.puts xunit_report task_list
end
Noop::Utils.debug "xUnit XML report was saved to: #{file_path_xunit_report.to_s}"
end
end
end

40
lib/noop/matchers.rb Normal file
View File

@ -0,0 +1,40 @@
module FuelRelationshipGraphMatchers
class EnsureTransitiveDependency
def initialize(before, after)
@before = before
@after = after
end
def matches?(actual_graph)
@actual_graph = actual_graph
@dependents = actual_graph.dependents(
vertex_called(actual_graph, @before))
!@dependents.find_all { |d| d.ref =~ /#{Regexp.escape(@after)}/i }.empty?
end
def failure_message
msg = "expected deployment graph to contain a transitional dependency between\n"
msg << "#{@before} and #{@after} but it did not happen\n"
msg << "#{@before} dependents are: #{@dependents.map {|dep| dep.ref}}\n"
msg
end
def failure_message_when_negated
msg = "expected deployment graph to NOT contain a transitional dependency between\n"
msg << "#{@before} and #{@after} but it did not happen\n"
msg << "#{@before} dependents are: #{@dependents.map {|dep| dep.ref}}\n"
msg
end
private
def vertex_called(graph, name)
graph.vertices.find { |v| v.ref =~ /#{Regexp.escape(name)}/i }
end
end
def ensure_transitive_dependency(before, after)
EnsureTransitiveDependency.new(before, after)
end
end

10
lib/noop/task.rb Normal file
View File

@ -0,0 +1,10 @@
require_relative 'config'
require_relative 'task/base'
require_relative 'task/facts'
require_relative 'task/globals'
require_relative 'task/hiera'
require_relative 'task/spec'
require_relative 'task/run'
require_relative 'task/overrides'
require_relative 'task/catalog'
require_relative 'task/helpers'

85
lib/noop/task/base.rb Normal file
View File

@ -0,0 +1,85 @@
module Noop
class Task
def initialize(spec=nil, hiera=nil, facts=nil)
self.status = :pending
self.file_name_spec = Noop::Utils.convert_to_spec spec if spec
self.file_name_hiera = hiera if hiera
self.file_name_facts = facts if facts
self.pid = Process.pid
self.thread = Thread.current.object_id
@parallel = false
Noop::Utils.warning "#{self}: Validation is failed!" unless valid?
end
attr_accessor :parallel
attr_accessor :pid
attr_accessor :thread
attr_accessor :status
def success?
status == :success
end
def failed?
status == :failed
end
def pending?
status == :pending
end
# @return [true,false]
def parallel_run?
parallel
end
# @return [true,false]
def valid?
unless file_path_spec.exist?
Noop::Utils.warning "No spec file: #{file_path_spec}!"
return false
end
unless file_path_manifest.exist?
Noop::Utils.warning "No task file: #{file_path_manifest}!"
return false
end
unless file_path_hiera.exist?
Noop::Utils.warning "No hiera file: #{file_path_hiera}!"
return false
end
unless file_path_facts.exist?
Noop::Utils.error "No facts file: #{file_path_hiera}!"
return false
end
true
end
# @return [String]
def to_s
"Task[#{file_base_spec}]"
end
def description
message = ''
message += "Task: #{file_name_manifest}"
message += " Spec: #{file_name_spec}"
message += " Hiera: #{file_name_hiera}"
message += " Facts: #{file_name_facts}"
message += " Status: #{status}"
message
end
def process_info
message = ''
message + "Object: #{object_id}"
message += " Pid: #{pid}" if pid
message += " Thread: #{thread}" if thread
message
end
# @return [Strong]
def inspect
"Task[#{description}]"
end
end
end

145
lib/noop/task/catalog.rb Normal file
View File

@ -0,0 +1,145 @@
require 'erb'
module Noop
class Task
# @return [String]
def status_report(context)
task = context.task
template = <<-'eof'
Facts: <%= task.file_path_facts %>
Hiera: <%= task.file_path_hiera %>
Spec: <%= task.file_path_spec %>
Manifest: <%= task.file_path_manifest %>
Node: <%= task.hiera_lookup 'fqdn' or '?' %>
Role: <%= task.hiera_lookup 'role' or '?' %>
Puppet: <%= Puppet.version %>
Ruby: <%= RUBY_VERSION %>
Hiera hierarchy:
<% task.hiera_hierarchy.each do |element| -%>
* <%= element %>
<% end -%>
Facts hierarchy:
<% task.facts_hierarchy.reverse.each do |element| -%>
* <%= element %>
<% end -%>
eof
ERB.new(template, nil, '-').result(binding)
end
# dumps the entire catalog structure to the text
# representation in the Puppet language
# @param context [Object] the context from the rspec test
# @param resources_filter [Array] the list of resources to dump. Dump all resources if not given
def catalog_dump(context, resources_filter = [])
catalog = context.subject
catalog = catalog.call if catalog.is_a? Proc
text = ''
resources_filter = [resources_filter] unless resources_filter.is_a? Array
catalog.resources.select do |catalog_resource|
if catalog_resource.type == 'Class'
next false if %w(main Settings).include? catalog_resource.title.to_s
end
next true unless resources_filter.any?
resources_filter.find do |filter_resource|
resources_are_same? catalog_resource, filter_resource
end
end.sort_by do |catalog_resource|
catalog_resource.to_s
end.each do |catalog_resource|
text += dump_resource(catalog_resource) + "\n"
text += "\n"
end
text
end
# takes a parameter value and formats it to the literal value
# that could be placed in the Puppet manifest
# @param value [String, Array, Hash, true, false, nil]
# @return [String]
def parameter_value_format(value)
case value
when TrueClass then 'true'
when FalseClass then 'false'
when NilClass then 'undef'
when Array then begin
array = value.collect do |v|
parameter_value_format v
end.join(', ')
"[ #{array} ]"
end
when Hash then begin
hash = value.keys.sort do |a, b|
a.to_s <=> b.to_s
end.collect do |key|
"#{parameter_value_format key.to_s} => #{parameter_value_format value[key]}"
end.join(', ')
"{ #{hash} }"
end
when Numeric, Symbol then parameter_value_format value.to_s
when String then begin
# escapes single quote characters and wrap into them
"'#{value.gsub "'", '\\\\\''}'"
end
else value.to_s
end
end
# take a resource object and generate a manifest representation of it
# in the Puppet language. Replaces "to_manifest" Puppet function which
# is not working correctly.
# @param resource [Puppet::Resource]
# @return [String]
def dump_resource(resource)
return '' unless resource.is_a? Puppet::Resource or resource.is_a? Puppet::Parser::Resource
attributes = resource.keys
if attributes.include?(:name) and resource[:name] == resource[:title]
attributes.delete(:name)
end
attribute_max_length = attributes.inject(0) do |max_length, attribute|
attribute.to_s.length > max_length ? attribute.to_s.length : max_length
end
attributes.sort!
if attributes.first != :ensure && attributes.include?(:ensure)
attributes.delete(:ensure)
attributes.unshift(:ensure)
end
attributes_text_block = attributes.map { |attribute|
value = resource[attribute]
" #{attribute.to_s.ljust attribute_max_length} => #{parameter_value_format value},\n"
}.join
"#{resource.type.to_s.downcase} { '#{resource.title.to_s}' :\n#{attributes_text_block}}"
end
# This function preprocesses both saved and generated
# catalogs before they will be compared. It allows us to ignore
# irrelevant changes in the catalogs:
# * ignore trailing whitespaces
# * ignore empty lines
# @param data [String]
# @return [String]
def preprocess_catalog_data(data)
clear_data = []
data.to_s.split("\n").each do |line|
line = line.rstrip
next if line == ''
clear_data << line
end
clear_data.join "\n"
end
# check if two resources have same type and title
# @param res1 [Puppet::Resource]
# @param res2 [Puppet::Resource]
# @return [TrueClass, False,Class]
def resources_are_same?(res1, res2)
res1 = res1.to_s.downcase.gsub %r|'"|, ''
res2 = res2.to_s.downcase.gsub %r|'"|, ''
res1 == res2
end
end
end

98
lib/noop/task/facts.rb Normal file
View File

@ -0,0 +1,98 @@
require 'yaml'
module Noop
class Task
# @return [Pathname]
def file_name_facts
return @file_name_facts if @file_name_facts
self.file_name_facts = Noop::Utils.path_from_env 'SPEC_FACTS_NAME'
return @file_name_facts if @file_name_facts
self.file_name_facts = Noop::Config.default_facts_file_name
@file_name_facts
end
alias :facts :file_name_facts
# @return [Pathname]
def file_name_facts=(value)
return if value.nil?
@file_name_facts = Noop::Utils.convert_to_path value
@file_name_facts = @file_name_facts.sub_ext '.yaml' if @file_name_facts.extname == ''
end
alias :facts= :file_name_facts=
# @return [Pathname]
def file_base_facts
file_name_facts.basename.sub_ext ''
end
# @return [Pathname]
def file_path_facts
Noop::Config.dir_path_facts + file_name_facts
end
# @return [true,false]
def file_present_facts?
return false unless file_path_facts
file_path_facts.readable?
end
# @return [Pathname]
def file_name_facts_override
file_name_task_extension
end
# @return [Pathname]
def file_path_facts_override
Noop::Config.dir_path_facts_override + file_name_facts_override
end
# @return [true,false]
def file_present_facts_override?
return unless file_path_facts_override
file_path_facts_override.readable?
end
# @return [Array<String>]
def facts_hierarchy
file_paths = []
file_paths << file_path_facts.to_s if file_present_facts?
file_paths << file_path_facts_override.to_s if file_present_facts_override?
file_paths
end
def add_host_names(facts_data)
hostname = hiera_lookup 'node_name'
fqdn = hiera_lookup 'fqdn'
facts_data[:hostname] = hostname if hostname
facts_data[:l3_fqdn_hostname] = hostname if hostname
facts_data[:fqdn] = fqdn if fqdn
end
# @return [Hash]
def facts_data
facts_data = {}
facts_hierarchy.each do |file_path|
begin
file_data = YAML.load_file file_path
next unless file_data.is_a? Hash
facts_data.merge! file_data
rescue
next
end
end
add_host_names facts_data
facts_data
end
alias :ubuntu_facts :facts_data
alias :centos_facts :facts_data
def hostname
facts_data[:hostname]
end
def fqdn
facts_data[:fqdn]
end
end
end

37
lib/noop/task/globals.rb Normal file
View File

@ -0,0 +1,37 @@
module Noop
class Task
# @return [Pathname]
def file_path_globals
Noop::Config.dir_path_globals + file_name_hiera
end
# @return [true,false]
def file_present_globals?
return false unless file_path_globals
file_path_globals.readable?
end
def write_file_globals(content)
File.open(file_path_globals.to_s, 'w') do |file|
file.write content
end
Noop::Utils.debug "Globals YAML saved to: '#{file_path_globals.to_s}'"
end
# @return [Pathname]
def file_name_globals
file_name_hiera
end
# @return [Pathname]
def file_base_globals
file_base_hiera
end
# @return [Pathname]
def element_globals
Noop::Config.dir_name_globals + file_base_globals
end
end
end

60
lib/noop/task/helpers.rb Normal file
View File

@ -0,0 +1,60 @@
module Noop
class Task
def resource_parameter_value(context, resource_type, resource_name, parameter)
catalog = context.subject
catalog = catalog.call if catalog.is_a? Proc
resource = catalog.resource resource_type, resource_name
fail "No resource type: '#{resource_type}' name: '#{resource_name}' in the catalog!" unless resource
resource[parameter.to_sym]
end
# save the current puppet scope
def puppet_scope=(value)
@puppet_scope = value
end
def puppet_scope
return @puppet_scope if @puppet_scope
PuppetlabsSpec::PuppetInternals.scope
end
# load a puppet function if it's not already loaded
def puppet_function_load(name)
name = name.to_sym unless name.is_a? Symbol
Puppet::Parser::Functions.autoloader.load name
end
# call a puppet function and return it's value
def puppet_function(name, *args)
name = name.to_sym unless name.is_a? Symbol
puppet_function_load name
fail "Could not load Puppet function '#{name}'!" unless puppet_scope.respond_to? "function_#{name}".to_sym
puppet_scope.send "function_#{name}".to_sym, args
end
# take a variable value from the saved puppet scope
def lookupvar(name)
puppet_scope.lookupvar name
end
# convert resource catalog to a RAL catalog
# and run "generate" hook for all resources
def create_ral_catalog(context)
catalog = context.subject
catalog = catalog.call if catalog.is_a? Proc
ral_catalog = catalog.to_ral
ral_catalog.resources.each do |resource|
next unless resource.respond_to? :generate
generated = resource.generate
next unless generated.is_a? Array
generated.each do |generated_resource|
next unless generated_resource.is_a? Puppet::Type
ral_catalog.add_resource generated_resource
end
end
lambda { ral_catalog }
end
end
end

146
lib/noop/task/hiera.rb Normal file
View File

@ -0,0 +1,146 @@
module Noop
class Task
# @return [Pathname]
def file_name_hiera
return @file_name_hiera if @file_name_hiera
self.file_name_hiera = Noop::Utils.path_from_env 'SPEC_ASTUTE_FILE_NAME', 'SPEC_HIERA_NAME'
return @file_name_hiera if @file_name_hiera
self.file_name_hiera = Noop::Config.default_hiera_file_name unless
@file_name_hiera
end
def file_name_hiera=(value)
return if value.nil?
@file_name_hiera = Noop::Utils.convert_to_path value
@file_name_hiera = @file_name_hiera.sub_ext '.yaml' if @file_name_hiera.extname == ''
end
# @return [Pathname]
def file_base_hiera
file_name_hiera.basename.sub_ext ''
end
# @return [Pathname]
def file_path_hiera
Noop::Config.dir_path_hiera + file_name_hiera
end
# @return [true,false]
def file_present_hiera?
return false unless file_path_hiera
file_path_hiera.readable?
end
# @return [Pathname]
def element_hiera
file_base_hiera
end
# @return [Pathname]
def file_name_hiera_override
file_name_task_extension
end
# @return [Pathname]
def file_path_hiera_override
Noop::Config.dir_path_hiera_override + file_name_hiera_override
end
# @return [true,false]
def file_present_hiera_override?
return unless file_path_hiera_override
file_path_hiera_override.readable?
end
# @return [Pathname]
def element_hiera_override
override_file = file_name_hiera_override
return unless override_file
Noop::Config.dir_name_hiera_override + override_file.sub_ext('')
end
# @return [String]
def hiera_logger
if ENV['SPEC_PUPPET_DEBUG']
'console'
else
'noop'
end
end
# @return [Array<String>]
def hiera_hierarchy
elements = []
elements << element_hiera_override.to_s if file_present_hiera_override?
elements << element_hiera.to_s if file_present_hiera?
elements << element_globals.to_s if file_present_globals?
elements
end
# @return [Hash]
def hiera_config
{
:backends => [
'yaml',
],
:yaml => {
:datadir => Noop::Config.dir_path_hiera.to_s,
},
:hierarchy => hiera_hierarchy,
:logger => hiera_logger,
:merge_behavior => :deeper,
}
end
# @return [Hiera]
def hiera_object
return @hiera_object if @hiera_object
@hiera_object = Hiera.new(:config => hiera_config)
Hiera.logger = hiera_config[:logger]
@hiera_object
end
# @return [Object]
def hiera_lookup(key, default = nil, resolution_type = :priority)
key = key.to_s
# def lookup(key, default, scope, order_override=nil, resolution_type=:priority)
hiera_object.lookup key, default, {}, nil, resolution_type
end
alias :hiera :hiera_lookup
# @return [Hash]
def hiera_hash(key, default = nil)
hiera_lookup key, default, :hash
end
# @return [Array]
def hiera_array(key, default = nil)
hiera_lookup key, default, :array
end
# @return [Object]
def hiera_structure(key, default = nil, separator = '/', resolution_type = :priority)
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 separator
key = path.shift
data = hiera key, nil, resolution_type
path_lookup.call data, path, default
end
end
end

View File

@ -0,0 +1,83 @@
module Noop
class Task
def setup_overrides
# puppet_default_settings
hiera_config_override
puppet_debug_override if ENV['SPEC_PUPPET_DEBUG']
setup_manifest
puppet_resource_scope_override
end
def setup_manifest
RSpec.configuration.manifest = file_path_manifest.to_s
RSpec.configuration.module_path = Noop::Config.dir_path_modules_local.to_s
RSpec.configuration.manifest_dir = Noop::Config.dir_path_tasks_local.to_s
end
def hiera_config_override
class << HieraPuppet
def hiera
@hiera ||= Hiera.new(:config => hiera_config)
Hiera.logger = 'noop'
@hiera
end
end
class << Hiera::Config
attr_accessor :config
def load(source)
@config ||= {}
end
def yaml_load_file(source)
@config ||= {}
end
def []=(key, value)
@config ||= {}
@config[key] = value
end
end
Hiera::Config.config = hiera_config
end
def puppet_resource_scope_override
Puppet::Parser::Resource.module_eval do
def initialize(*args)
raise ArgumentError, "Resources require a hash as last argument" unless args.last.is_a? Hash
raise ArgumentError, "Resources require a scope" unless args.last[:scope]
super
Noop.task.puppet_scope = scope
@source ||= scope.source
end
end
end
def puppet_debug_override
Puppet::Util::Log.level = :debug
Puppet::Util::Log.newdestination(:console)
end
# These settings are pulled from the Puppet TestHelper
# (See Puppet::Test::TestHelper.initialize_settings_before_each)
# These items used to be setup in puppet 3.4 but were moved to before tests
# which breaks our testing framework because we attempt to call
# PuppetlabsSpec::PuppetInternals.scope and
# Puppet::Parser::Function.autoload.load prior to the testing being run.
# This results in an rspec failure so we need to initialize the basic
# settings up front to prevent issues with test framework. See PUP-5601
def puppet_default_settings
Puppet.settings.initialize_app_defaults(
{
:logdir => '/dev/null',
:confdir => '/dev/null',
:vardir => '/dev/null',
:rundir => '/dev/null',
:hiera_config => '/dev/null',
}
)
end
end
end

98
lib/noop/task/run.rb Normal file
View File

@ -0,0 +1,98 @@
require 'json'
module Noop
class Task
def run
return unless pending?
self.pid = Process.pid
self.thread = Thread.current.object_id
Noop::Utils.debug "RUN: #{self.inspect}"
file_remove_report_json
rspec_command_run
file_load_report_json
determine_task_status
Noop::Utils.debug "FINISH: #{self.inspect}"
status
end
def file_load_report_json
self.report = file_data_report_json
end
def set_status_value(value)
if value.is_a? TrueClass
self.status = :success
elsif value.is_a? FalseClass
self.status = :failed
else
self.status = :pending
end
end
def determine_task_status
if report.is_a? Hash
failures = report.fetch('summary', {}).fetch('failure_count', nil)
if failures.is_a? Numeric
set_status_value(failures == 0)
end
end
status
end
# @return [Pathname]
def file_name_report_json
Noop::Utils.convert_to_path "#{file_name_task_extension.sub_ext ''}_#{file_base_hiera}_#{file_base_facts}.json"
end
# @return [Pathname]
def file_path_report_json
Noop::Config.dir_path_reports + file_name_report_json
end
# @return [Hash]
def file_data_report_json
return unless file_present_report_json?
file_data = nil
begin
file_content = File.read file_path_report_json.to_s
file_data = JSON.load file_content
return unless file_data.is_a? Hash
rescue
nil
end
file_data
end
def file_remove_report_json
file_path_report_json.unlink if file_present_report_json?
end
# @return [true,false]
def file_present_report_json?
file_path_report_json.exist?
end
def rspec_options
options = '--color --tty'
options += ' --format documentation' unless parallel_run?
options
end
# @return [true,false]
def rspec_command_run
environment = {
'SPEC_HIERA_NAME' => file_name_hiera.to_s,
'SPEC_FACTS_NAME' => file_name_facts.to_s,
'SPEC_FILE_NAME' => file_name_spec.to_s,
}
command = "rspec #{file_path_spec.to_s} #{rspec_options} --format json --out #{file_path_report_json.to_s}"
command = "bundle exec #{command}" if ENV['SPEC_BUNDLE_EXEC']
Dir.chdir Noop::Config.dir_path_root
success = Noop::Utils.run environment, command
set_status_value success
success
end
attr_accessor :report
end
end

48
lib/noop/task/spec.rb Normal file
View File

@ -0,0 +1,48 @@
module Noop
class Task
# @return [Pathname]
def file_name_spec
return @file_name_spec if @file_name_spec
self.file_name_spec = Noop::Utils.path_from_env 'SPEC_FILE_NAME'
@file_name_spec
end
# @return [Pathname]
def file_base_spec
Noop::Utils.convert_to_path(file_name_spec.to_s.gsub /_spec\.rb$/, '')
end
# @return [Pathname]
def file_name_spec=(value)
return if value.nil?
@file_name_spec = Noop::Utils.convert_to_spec value
@file_name_spec
end
# @return [Pathname]
def file_name_manifest
Noop::Utils.convert_to_manifest file_name_spec
end
# @return [Pathname]
def file_path_manifest
Noop::Config.dir_path_tasks_local + file_name_manifest
end
# @return [Pathname]
def file_path_spec
Noop::Config.dir_path_task_spec + file_name_spec
end
# @return [true,false]
def file_present_spec
file_path_spec.readable?
end
# @return [Pathname]
def file_name_task_extension
Noop::Utils.convert_to_path(file_base_spec.to_s.gsub('/', '-') + '.yaml')
end
end
end

81
lib/noop/utils.rb Normal file
View File

@ -0,0 +1,81 @@
module Noop
module Utils
# @param [Array<String>, String] names
# @return [Pathname, nil]
def self.path_from_env(*names)
names.each do |name|
name = name.to_s
return convert_to_path ENV[name] if ENV[name]
end
nil
end
# @param [Object] value
# @return [Pathname]
def self.convert_to_path(value)
value = Pathname.new value.to_s unless value.is_a? Pathname
value
end
def self.convert_to_manifest(spec)
manifest = spec.to_s.gsub /_spec\.rb$/, '.pp'
convert_to_path manifest
end
def self.convert_to_spec(value)
value = value.to_s.chomp.strip
value = value[0...-3] if value.end_with? '.pp'
value += '_spec.rb' unless value.end_with? '_spec.rb'
convert_to_path value
end
def self.convert_to_yaml(value)
value = value.to_s.chomp.strip
value = convert_to_path value
value = value.sub /$/, '.yaml' unless value.extname =~ /\.yaml/i
value
end
# Run the code block inside the tests directory
# and then return back
def self.inside_task_root_dir
current_directory = Dir.pwd
Dir.chdir Noop::Config.dir_path_root
result = yield
Dir.chdir current_directory if current_directory
result
end
# Run the code block inside the deployment driectory
# and then return back
def self.inside_deployment_directory
current_directory = Dir.pwd
Dir.chdir Noop::Config.dir_path_deployment
result = yield
Dir.chdir current_directory if current_directory
result
end
def self.run(*args)
debug "CMD: #{args.inspect} PWD: #{Dir.pwd}"
system *args
end
def self.debug(message)
Noop::Config.log.debug message
end
def self.info(message)
Noop::Config.log.info message
end
def self.warning(message)
Noop::Config.log.warn message
end
def self.error(message)
Noop::Config.log.fatal message
exit(1)
end
end
end

0
modules/.gitkeep Normal file
View File

9
noop_tests.rb Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env ruby
require_relative 'lib/noop/config'
require_relative 'lib/noop/task'
require_relative 'lib/noop/manager'
require_relative 'lib/noop/utils'
manager = Noop::Manager.new
manager.main

2
reports/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.xml
*.json

1
spec/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
hosts

137
spec/lib/config_spec.rb Normal file
View File

@ -0,0 +1,137 @@
require 'spec_helper'
require 'noop/config'
describe Noop::Config do
let (:root) do
File.absolute_path File.join File.dirname(__FILE__), '..', '..'
end
context 'base' do
it 'dir_path_config' do
expect(subject.dir_path_config).to be_a Pathname
expect(subject.dir_path_config.to_s).to eq "#{root}/lib/noop/config"
end
it 'dir_path_root' do
expect(subject.dir_path_root).to be_a Pathname
expect(subject.dir_path_root.to_s).to eq root
end
it 'dir_path_task_spec' do
expect(subject.dir_path_task_spec).to be_a Pathname
expect(subject.dir_path_task_spec.to_s).to eq "#{root}/spec/hosts"
end
it 'dir_path_modules_local' do
expect(subject.dir_path_modules_local).to be_a Pathname
expect(subject.dir_path_modules_local.to_s).to eq "#{root}/modules"
end
it 'dir_path_tasks_local' do
expect(subject.dir_path_tasks_local).to be_a Pathname
expect(subject.dir_path_tasks_local.to_s).to eq "#{root}/tasks"
end
it 'dir_path_modules_node' do
expect(subject.dir_path_modules_node).to be_a Pathname
expect(subject.dir_path_modules_node.to_s).to eq '/etc/puppet/modules'
end
it 'dir_path_tasks_node' do
expect(subject.dir_path_tasks_node).to be_a Pathname
expect(subject.dir_path_tasks_node.to_s).to eq '/etc/puppet/modules/osnailyfacter/modular'
end
it 'dir_path_deployment' do
expect(subject.dir_path_deployment).to be_a Pathname
expect(subject.dir_path_deployment.to_s).to eq "#{root}/deployment"
end
it 'dir_path_workspace' do
expect(subject.dir_path_workspace).to be_a Pathname
expect(subject.dir_path_workspace.to_s).to eq "#{root}/workspace"
end
it 'dir_path_reports' do
expect(subject.dir_path_reports).to be_a Pathname
expect(subject.dir_path_reports.to_s).to eq "#{root}/reports"
end
end
context 'hiera' do
it 'dir_name_hiera' do
expect(subject.dir_name_hiera).to be_a Pathname
expect(subject.dir_name_hiera.to_s).to eq 'hiera'
end
it 'dir_path_hiera' do
expect(subject.dir_path_hiera).to be_a Pathname
expect(subject.dir_path_hiera.to_s).to eq "#{root}/hiera"
end
it 'dir_name_hiera_override' do
expect(subject.dir_name_hiera_override).to be_a Pathname
expect(subject.dir_name_hiera_override.to_s).to eq 'override'
end
it 'dir_path_hiera_override' do
expect(subject.dir_path_hiera_override).to be_a Pathname
expect(subject.dir_path_hiera_override.to_s).to eq "#{root}/hiera/override"
end
end
context 'facts' do
it 'dir_name_facts' do
expect(subject.dir_name_facts).to be_a Pathname
expect(subject.dir_name_facts.to_s).to eq 'facts'
end
it 'dir_path_facts' do
expect(subject.dir_path_facts).to be_a Pathname
expect(subject.dir_path_facts.to_s).to eq "#{root}/facts"
end
it 'dir_name_facts_override' do
expect(subject.dir_name_facts_override).to be_a Pathname
expect(subject.dir_name_facts_override.to_s).to eq 'override'
end
it 'dir_path_facts_override' do
expect(subject.dir_path_facts_override).to be_a Pathname
expect(subject.dir_path_facts_override.to_s).to eq "#{root}/facts/override"
end
end
context 'globals' do
it 'spec_name_globals' do
expect(subject.spec_name_globals).to be_a Pathname
expect(subject.spec_name_globals.to_s).to eq 'globals/globals_spec.rb'
end
it 'spec_path_globals' do
expect(subject.spec_path_globals).to be_a Pathname
expect(subject.spec_path_globals.to_s).to eq "#{root}/spec/hosts/globals/globals_spec.rb"
end
it 'manifest_name_globals' do
expect(subject.manifest_name_globals).to be_a Pathname
expect(subject.manifest_name_globals.to_s).to eq 'globals/globals.pp'
end
it 'manifest_path_globals' do
expect(subject.manifest_path_globals).to be_a Pathname
expect(subject.manifest_path_globals.to_s).to eq "#{root}/tasks/globals/globals.pp"
end
it 'dir_name_globals' do
expect(subject.dir_name_globals).to be_a Pathname
expect(subject.dir_name_globals.to_s).to eq 'globals'
end
it 'dir_path_globals' do
expect(subject.dir_path_globals).to be_a Pathname
expect(subject.dir_path_globals.to_s).to eq "#{root}/hiera/globals"
end
end
end

202
spec/lib/task_spec.rb Normal file
View File

@ -0,0 +1,202 @@
require 'spec_helper'
require 'noop/task'
describe Noop::Task do
before(:each) do
allow(Noop::Utils).to receive(:warning)
end
subject do
Noop::Task.new 'my/test_spec.rb'
end
let (:root) do
File.absolute_path File.join File.dirname(__FILE__), '..', '..'
end
context 'base' do
it 'should have status' do
is_expected.to respond_to :status
end
it 'should have success?' do
subject.status = :pending
is_expected.not_to be_success
subject.status = :success
is_expected.to be_success
end
it 'should have pending?' do
subject.status = :failed
is_expected.not_to be_pending
subject.status = :pending
is_expected.to be_pending
end
it 'should have failed?' do
subject.status = :success
is_expected.not_to be_failed
subject.status = :failed
is_expected.to be_failed
end
it 'should have parallel_run?' do
is_expected.not_to be_parallel_run
subject.parallel = true
is_expected.to be_parallel_run
end
it 'should have valid?' do
is_expected.not_to be_valid
end
it 'should have to_s' do
expect(subject.to_s).to eq 'Task[my/test]'
end
it 'should have inspect' do
expect(subject.inspect).to eq 'Task[Task: my/test.pp Spec: my/test_spec.rb Hiera: novanet-primary-controller.yaml Facts: ubuntu.yaml Status: pending]'
end
end
context 'spec' do
it 'has file_name_spec' do
expect(subject.file_name_spec).to be_a Pathname
expect(subject.file_name_spec.to_s).to eq 'my/test_spec.rb'
end
it 'can set file_name_spec' do
subject.file_name_spec = 'my/test2_spec.rb'
expect(subject.file_name_spec).to be_a Pathname
expect(subject.file_name_spec.to_s).to eq 'my/test2_spec.rb'
end
it 'will get spec name from the manifest name' do
subject.file_name_spec = 'my/test3.pp'
expect(subject.file_name_spec).to be_a Pathname
expect(subject.file_name_spec.to_s).to eq 'my/test3_spec.rb'
end
it 'has file_name_manifest' do
expect(subject.file_name_manifest).to be_a Pathname
expect(subject.file_name_manifest.to_s).to eq 'my/test.pp'
end
it 'has file_path_manifest' do
expect(subject.file_path_manifest).to be_a Pathname
expect(subject.file_path_manifest.to_s).to eq "#{root}/tasks/my/test.pp"
end
it 'has file_path_spec' do
expect(subject.file_path_spec).to be_a Pathname
expect(subject.file_path_spec.to_s).to eq "#{root}/spec/hosts/my/test_spec.rb"
end
end
context 'facts' do
it 'has file_name_facts' do
expect(subject.file_name_facts).to be_a Pathname
expect(subject.file_name_facts.to_s).to eq 'ubuntu.yaml'
end
it 'can set file_name_facts' do
subject.file_name_facts = 'master.yaml'
expect(subject.file_name_facts).to be_a Pathname
expect(subject.file_name_facts.to_s).to eq 'master.yaml'
end
it 'will add yaml extension to the facts name' do
subject.file_name_facts = 'centos'
expect(subject.file_name_facts).to be_a Pathname
expect(subject.file_name_facts.to_s).to eq 'centos.yaml'
end
it 'has file_path_facts' do
expect(subject.file_path_facts).to be_a Pathname
expect(subject.file_path_facts.to_s).to eq "#{root}/facts/ubuntu.yaml"
end
it 'has file_name_facts_override' do
expect(subject.file_name_facts_override).to be_a Pathname
expect(subject.file_name_facts_override.to_s).to eq 'my-test.yaml'
end
it 'has file_path_facts_override' do
expect(subject.file_path_facts_override).to be_a Pathname
expect(subject.file_path_facts_override.to_s).to eq "#{root}/facts/override/my-test.yaml"
end
end
context 'hiera' do
it 'has file_name_hiera' do
expect(subject.file_name_hiera).to be_a Pathname
expect(subject.file_name_hiera.to_s).to eq 'novanet-primary-controller.yaml'
end
it 'has file_base_hiera' do
expect(subject.file_base_hiera).to be_a Pathname
expect(subject.file_base_hiera.to_s).to eq 'novanet-primary-controller'
end
it 'has element_hiera' do
expect(subject.element_hiera).to be_a Pathname
expect(subject.element_hiera.to_s).to eq 'novanet-primary-controller'
end
it 'can set file_name_hiera' do
subject.file_name_hiera = 'compute.yaml'
expect(subject.file_name_hiera).to be_a Pathname
expect(subject.file_name_hiera.to_s).to eq 'compute.yaml'
end
it 'will add yaml extension to the hiera name' do
subject.file_name_hiera = 'controller'
expect(subject.file_name_hiera).to be_a Pathname
expect(subject.file_name_hiera.to_s).to eq 'controller.yaml'
end
it 'has file_path_hiera' do
expect(subject.file_path_hiera).to be_a Pathname
expect(subject.file_path_hiera.to_s).to eq "#{root}/hiera/novanet-primary-controller.yaml"
end
it 'has file_name_hiera_override' do
expect(subject.file_name_hiera_override).to be_a Pathname
expect(subject.file_name_hiera_override.to_s).to eq 'my-test.yaml'
end
it 'has file_path_hiera_override' do
expect(subject.file_path_hiera_override).to be_a Pathname
expect(subject.file_path_hiera_override.to_s).to eq "#{root}/hiera/override/my-test.yaml"
end
it 'has element_hiera_override' do
expect(subject.element_hiera_override).to be_a Pathname
expect(subject.element_hiera_override.to_s).to eq 'override/my-test'
end
end
context 'globals' do
it 'has file_path_globals' do
expect(subject.file_path_globals).to be_a Pathname
expect(subject.file_path_globals.to_s).to eq "#{root}/hiera/globals/novanet-primary-controller.yaml"
end
it 'has file_name_globals' do
expect(subject.file_name_globals).to be_a Pathname
expect(subject.file_name_globals.to_s).to eq 'novanet-primary-controller.yaml'
end
it 'has file_base_globals' do
expect(subject.file_base_globals).to be_a Pathname
expect(subject.file_base_globals.to_s).to eq 'novanet-primary-controller'
end
it 'has element_globals' do
expect(subject.element_globals).to be_a Pathname
expect(subject.element_globals.to_s).to eq 'globals/novanet-primary-controller'
end
end
end

84
spec/shared-examples.rb Normal file
View File

@ -0,0 +1,84 @@
shared_examples 'compile' do
it { is_expected.to compile }
end
shared_examples 'show_catalog' do
it 'shows catalog contents' do
puts '=' * 80
puts Noop.task.catalog_dump self
puts '=' * 80
end
end
shared_examples 'status' do
it 'shows status' do
puts '=' * 80
puts Noop.task.status_report self
puts '=' * 80
end
end
shared_examples 'console' do
it 'runs pry console' do
require 'pry'
binding.pry
end
end
###############################################################################
def run_test(manifest_file, *args)
Noop.task_spec = manifest_file unless Noop.task_spec
Noop::Config.log.progname = 'noop_spec'
Noop::Utils.debug "RSPEC: #{Noop.task.inspect}"
include FuelRelationshipGraphMatchers
let(:task) do
Noop.task
end
before(:all) do
Noop.setup_overrides
end
let(:facts) do
Noop.facts_data
end
let (:catalog) do
catalog = subject
catalog = catalog.call if catalog.is_a? Proc
end
let (:ral) do
ral = catalog.to_ral
ral.finalize
ral
end
let (:graph) do
graph = Puppet::Graph::RelationshipGraph.new(Puppet::Graph::TitleHashPrioritizer.new)
graph.populate_from(ral)
graph
end
include_examples 'compile'
include_examples 'status' if ENV['SPEC_SHOW_STATUS']
include_examples 'show_catalog' if ENV['SPEC_CATALOG_SHOW']
include_examples 'console' if ENV['SPEC_RSPEC_CONSOLE']
begin
include_examples 'catalog'
rescue ArgumentError
true
end
yield self if block_given?
end
alias :test_ubuntu_and_centos :run_test
alias :test_ubuntu :run_test
alias :test_centos :run_test

30
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,30 @@
require 'rubygems'
require 'puppet'
require 'hiera_puppet'
require 'rspec-puppet'
require 'rspec-puppet-utils'
require 'puppetlabs_spec_helper/module_spec_helper'
require_relative '../lib/noop'
# Add fixture lib dirs to LOAD_PATH. Work-around for PUP-3336
if Puppet.version < '4.0.0'
Dir["#{Noop::Config.dir_path_modules_local}/*/lib"].entries.each do |lib_dir|
$LOAD_PATH << lib_dir
end
end
RSpec.configure do |c|
c.mock_with :rspec
c.expose_current_running_example_as :example
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
end
end

0
workspace/.gitkeep Normal file
View File