Add new framework library
Partial blueprint: deployment-data-dryrun Change-Id: Ifd81c68e5f08e02ab3c2df2910eab073a743f941
This commit is contained in:
parent
8fa5c3c06c
commit
c60235736c
|
@ -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,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
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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,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
|
|
@ -0,0 +1,2 @@
|
|||
*.xml
|
||||
*.json
|
|
@ -0,0 +1 @@
|
|||
hosts
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue