Revision e86db516
Added by Dmitri Dolguikh almost 9 years ago
config/settings.d/puppet.yml.example | ||
---|---|---|
|
||
# Cache options
|
||
#:use_cache: true
|
||
# default location of cache is relative to the installation dir
|
||
#:cache_location: '/var/lib/smart-proxy/cache'
|
modules/puppet_proxy/class_scanner.rb | ||
---|---|---|
module Proxy::Puppet
|
||
class ClassScanner < ClassScannerBase
|
||
class << self
|
||
# scans a given directory and its sub directory for puppet classes
|
||
# returns an array of PuppetClass objects.
|
||
def scan_directory directory, environment
|
||
super directory, environment
|
||
end
|
||
|
||
def scan_manifest manifest, filename = ''
|
||
Proxy::Puppet::Initializer.load
|
||
parser = Puppet::Parser::Parser.new Puppet::Node::Environment.new
|
||
klasses = []
|
||
|
modules/puppet_proxy/class_scanner_base.rb | ||
---|---|---|
require 'puppet_proxy/puppet_cache'
|
||
|
||
module Proxy::Puppet
|
||
class ClassScannerBase
|
||
class << self
|
||
# scans a given directory and its sub directory for puppet classes using the parser passed to it
|
||
# returns an array of PuppetClass objects.
|
||
def scan_directory directory, environment
|
||
if Proxy::Puppet::Plugin.settings.use_cache
|
||
PuppetCache.scan_directory_with_cache(directory, environment, self)
|
||
else
|
||
Dir.glob("#{directory}/*/manifests/**/*.pp").map do |filename|
|
||
scan_manifest File.read(filename), filename
|
||
end.compact.flatten
|
||
end
|
||
Dir.glob("#{directory}/*/manifests/**/*.pp").map do |filename|
|
||
scan_manifest File.read(filename), filename
|
||
end.compact.flatten
|
||
end
|
||
end
|
||
end
|
modules/puppet_proxy/class_scanner_eparser.rb | ||
---|---|---|
require 'puppet'
|
||
require 'puppet_proxy/class_scanner_base'
|
||
|
||
# this is needed to support tests in environments with puppet version < 3.2
|
||
module Proxy::Puppet
|
||
class ClassScannerEParser < ClassScannerBase; end
|
||
end
|
||
|
||
if Puppet::PUPPETVERSION.to_f >= 3.2
|
||
require 'puppet/pops'
|
||
|
||
module Proxy::Puppet
|
||
class ClassScannerEParser < ClassScannerBase
|
||
class << self
|
||
|
||
# scans a given directory and its sub directory for puppet classes
|
||
# returns an array of PuppetClass objects.
|
||
def scan_directory directory, environment
|
||
super directory, environment
|
||
end
|
||
|
||
def scan_manifest manifest, filename = ''
|
||
Proxy::Puppet::Initializer.load
|
||
klasses = []
|
||
|
||
already_seen = Set.new
|
modules/puppet_proxy/class_scanner_factory.rb | ||
---|---|---|
require 'puppet_proxy/class_scanner'
|
||
require 'puppet_proxy/class_scanner_eparser'
|
||
require 'puppet_proxy/puppet_cache'
|
||
|
||
module Proxy::Puppet
|
||
class ClassScannerFactory
|
||
def initialize(use_eparser)
|
||
@use_eparser = use_eparser
|
||
end
|
||
|
||
def scanner
|
||
parser = @use_eparser ? ::Proxy::Puppet::ClassScannerEParser : ::Proxy::Puppet::ClassScanner
|
||
|
||
if Proxy::Puppet::Plugin.settings.use_cache
|
||
@@cached ||= PuppetCache.new(parser, MemoryStore.new, MemoryStore.new)
|
||
else
|
||
parser
|
||
end
|
||
end
|
||
end
|
||
end
|
modules/puppet_proxy/environment.rb | ||
---|---|---|
require 'puppet_proxy/config_reader'
|
||
require 'puppet_proxy/puppet_class'
|
||
require 'puppet_proxy/api_request'
|
||
require 'puppet_proxy/class_scanner_factory'
|
||
require 'proxy/util'
|
||
|
||
class Proxy::Puppet::Environment
|
||
... | ... | |
::Proxy::Puppet::Initializer.load
|
||
conf = ::Proxy::Puppet::ConfigReader.new(::Proxy::Puppet::Initializer.config).get
|
||
eparser = (conf[:main] && conf[:main][:parser] == 'future') || (conf[:master] && conf[:master][:parser] == 'future')
|
||
scanner = ::Proxy::Puppet::ClassScannerFactory.new(eparser).scanner
|
||
|
||
paths.map {|path| ::Proxy::Puppet::PuppetClass.scan_directory path, name, eparser}.flatten
|
||
paths.map {|path| scanner.scan_directory(path, name) }.flatten
|
||
end
|
||
end
|
||
end
|
modules/puppet_proxy/memory_store.rb | ||
---|---|---|
module Proxy::Puppet
|
||
class MemoryStore
|
||
def initialize
|
||
@root = {}
|
||
end
|
||
|
||
def [](*path)
|
||
get(@root, path)
|
||
end
|
||
|
||
def []=(*args)
|
||
value = args.pop
|
||
put(@root, args, value)
|
||
end
|
||
|
||
def values(*path)
|
||
get_all_values(get(@root, path))
|
||
end
|
||
|
||
private
|
||
|
||
def get(store, path)
|
||
ret_val = store[path.first]
|
||
return ret_val if path.size == 1
|
||
ret_val ? get(ret_val, path.slice(1, path.size - 1)) : nil
|
||
end
|
||
|
||
def put(store, path, value)
|
||
return store[path.first] = value if path.size == 1
|
||
|
||
store[path.first] = {} unless store.key?(path.first)
|
||
put(store[path.first], path.slice(1, path.size - 1), value)
|
||
end
|
||
|
||
def get_all_values(store)
|
||
store.inject([]) do |acc, current|
|
||
acc + (current.last.is_a?(Hash) ? get_all_values(current.last) : [current.last])
|
||
end.flatten
|
||
end
|
||
end
|
||
end
|
modules/puppet_proxy/puppet_cache.rb | ||
---|---|---|
require 'json'
|
||
require 'puppet_proxy/memory_store'
|
||
require 'thread'
|
||
|
||
module Proxy::Puppet
|
||
class PuppetCache
|
||
extend Proxy::Log
|
||
class << self
|
||
def scan_directory_with_cache directory, environment, scanner
|
||
logger.info("Running scan_directory on #{environment}: #{directory}")
|
||
include Proxy::Log
|
||
|
||
cache = read_from_cache(environment)
|
||
attr_reader :class_scanner
|
||
|
||
if cache.has_key?(directory)
|
||
lcache = cache[directory]
|
||
else
|
||
lcache = {}
|
||
end
|
||
|
||
seenmodules=[]
|
||
changed = false
|
||
manifest = Dir.glob("#{directory}/*").map do |path|
|
||
puppetmodule = File.basename(path)
|
||
mtime = File.mtime(path).to_i
|
||
seenmodules.push(puppetmodule)
|
||
|
||
lcache[puppetmodule] = {} unless lcache.has_key?(puppetmodule)
|
||
if lcache[puppetmodule].has_key?('timestamp') && lcache[puppetmodule]['timestamp'] >= mtime
|
||
logger.debug("Using cached class #{puppetmodule}")
|
||
modulemanifest = lcache[puppetmodule]['manifest']
|
||
else
|
||
changed = true
|
||
logger.info("Scanning class #{puppetmodule}")
|
||
modulemanifest = Dir.glob("#{path}/manifests/**/*.pp").map do |filename|
|
||
scanner.scan_manifest File.read(filename), filename
|
||
end
|
||
|
||
lcache[puppetmodule]['timestamp']= Time.new.to_i
|
||
lcache[puppetmodule]['manifest'] = modulemanifest
|
||
end
|
||
modulemanifest
|
||
end.compact.flatten
|
||
|
||
if changed
|
||
logger.info("Cache file need to be updated for #{environment}: #{directory}")
|
||
# Clean obsolete cache modules
|
||
oldlength = lcache.length
|
||
lcache.delete_if { |key, value| !seenmodules.include?(key) }
|
||
logger.info("Cleaning #{oldlength - lcache.length } modules from cache") if oldlength - lcache.length > 0
|
||
|
||
cache[directory] = lcache
|
||
write_to_cache(cache, environment)
|
||
logger.info("Cache file updated for #{environment}: #{directory}")
|
||
end
|
||
|
||
manifest
|
||
end
|
||
|
||
def read_from_cache environment
|
||
cachefile = File.expand_path("cache_#{environment}.json", Proxy::Puppet::Plugin.settings.cache_location)
|
||
def initialize(class_scanner, classes_store, timestamps_store)
|
||
@classes_cache = classes_store
|
||
@timestamps = timestamps_store
|
||
@class_scanner = class_scanner
|
||
@mutex = Mutex.new
|
||
end
|
||
|
||
if File.exist?(cachefile)
|
||
as_hash = JSON.load(File.new(cachefile))
|
||
def scan_directory directory, environment
|
||
logger.debug("Running scan_directory on #{environment}: #{directory}")
|
||
|
||
if as_hash.delete('version') != ::Proxy::Puppet::Plugin.version
|
||
logger.info("Mismatching puppet cache version, discarding.")
|
||
return {}
|
||
end
|
||
@mutex.synchronize do
|
||
tmp_classes = MemoryStore.new
|
||
tmp_timestamps = MemoryStore.new
|
||
|
||
# ran into issues with deserialisation in older versions of json gem (ruby 1.8.7 + json 1.5.5),
|
||
# and opted for the deserialisation approach below.
|
||
# TODO: switch back to json library based deserialisation by implementing PuppetClass.json_create
|
||
# when support for Ruby 1.8.7 has been dropped.
|
||
as_hash.values.each do |dir|
|
||
dir.values.each do |puppet_module|
|
||
puppet_module['manifest'] =
|
||
puppet_module['manifest'].flatten.map { |klass| [Proxy::Puppet::PuppetClass.from_hash(klass)] }
|
||
Dir.glob("#{directory}/*").map do |path|
|
||
puppetmodule = File.basename(path)
|
||
Dir.glob("#{path}/manifests/**/*.pp").map do |filename|
|
||
if @timestamps[directory, filename] && (File.mtime(filename).to_i <= @timestamps[directory, filename])
|
||
logger.debug("Using #{puppetmodule} cached classes from #{filename}")
|
||
tmp_classes[directory, filename] = @classes_cache[directory, filename]
|
||
tmp_timestamps[directory, filename] = @timestamps[directory, filename]
|
||
else
|
||
logger.debug("Scanning #{puppetmodule} classes in #{filename}")
|
||
tmp_classes[directory, filename] = class_scanner.scan_manifest File.read(filename), filename
|
||
tmp_timestamps[directory, filename] = File.mtime(filename).to_i
|
||
end
|
||
end
|
||
as_hash
|
||
else
|
||
{}
|
||
end
|
||
end
|
||
|
||
def write_to_cache cache, environment
|
||
cache_dir = Proxy::Puppet::Plugin.settings.cache_location
|
||
FileUtils.mkdir_p(cache_dir) unless File.directory?(cache_dir)
|
||
@classes_cache[directory] = tmp_classes[directory]
|
||
@timestamps[directory] = tmp_timestamps[directory]
|
||
|
||
cachefile = File.expand_path("cache_#{environment}.json", cache_dir)
|
||
lock = Proxy::FileLock.try_locking(cachefile)
|
||
|
||
unless lock.nil?
|
||
tmpfile = cachefile + '.tmp'
|
||
to_serialise = cache.merge('version' => ::Proxy::Puppet::Plugin.version)
|
||
File.open(tmpfile, 'w') { |file| file.write(to_serialise.to_json) }
|
||
File.rename(tmpfile, cachefile)
|
||
Proxy::FileLock.unlock(lock)
|
||
end
|
||
@classes_cache[directory] ? @classes_cache.values(directory).compact : []
|
||
end
|
||
end
|
||
end
|
modules/puppet_proxy/puppet_class.rb | ||
---|---|---|
require 'puppet_proxy/class_scanner_eparser'
|
||
|
||
class Proxy::Puppet::PuppetClass
|
||
class << self
|
||
# scans a given directory and its sub directory for puppet classes
|
||
# returns an array of PuppetClass objects.
|
||
def scan_directory directory, environment, eparser = false
|
||
# Get a Puppet Parser to parse the manifest source
|
||
Proxy::Puppet::Initializer.load
|
||
|
||
if eparser
|
||
Proxy::Puppet::ClassScannerEParser.scan_directory directory, environment
|
||
else
|
||
Proxy::Puppet::ClassScanner.scan_directory directory, environment
|
||
end
|
||
end
|
||
end
|
||
|
||
def initialize name, params = {}
|
||
@klass = name || raise("Must provide puppet class name")
|
||
@params = params
|
modules/puppet_proxy/puppet_plugin.rb | ||
---|---|---|
https_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
|
||
|
||
default_settings :puppet_provider => 'puppetrun', :puppetdir => '/etc/puppet', :use_cache => true,
|
||
:cache_location => File.expand_path("cache", File.expand_path("../../../", __FILE__)),
|
||
:salt_puppetrun_cmd => 'puppet.run'
|
||
plugin :puppet, ::Proxy::VERSION
|
||
end
|
test/fixtures/modules_include/testinclude/manifests/sub/foo.pp | ||
---|---|---|
class testinclude::sub::foo {
|
||
class testinclude::sub::foo(
|
||
$param1 = "first_parameter",
|
||
$param2 = "second_parameter"
|
||
) {
|
||
}
|
test/puppet/class_scanner_eparser_test.rb | ||
---|---|---|
assert klasses.any? {|k| k.name == "testinclude" }
|
||
end
|
||
|
||
def test_should_handle_import_in_a_manifest_with_cache
|
||
return unless Puppet::PUPPETVERSION.to_f >= 3.2
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => true)
|
||
|
||
Proxy::Puppet::PuppetCache.stubs(:read_from_cache).returns(
|
||
'./test/fixtures/modules_include' => { 'testinclude' => { 'timestamp' => Time.now.to_i,
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('testinclude')],
|
||
[Proxy::Puppet::PuppetClass.new('testinclude::check::cache')]] }})
|
||
Proxy::Puppet::PuppetCache.stubs(:write_to_cache)
|
||
|
||
klasses = Proxy::Puppet::ClassScannerEParser.scan_directory('./test/fixtures/modules_include', "example_env")
|
||
assert_equal 2, klasses.size
|
||
|
||
klass = klasses.find {|k| k.name == "check::cache" }
|
||
assert klass
|
||
assert_equal "testinclude", klass.module
|
||
|
||
assert klasses.any? {|k| k.name == "testinclude" }
|
||
end
|
||
|
||
#TODO add scans to a real puppet directory with modules
|
||
|
||
end
|
test/puppet/class_scanner_factory_test.rb | ||
---|---|---|
require 'test_helper'
|
||
require 'puppet_proxy/puppet_plugin'
|
||
require 'puppet/testing_class_scanner_factory'
|
||
|
||
class ClassScannerFactoryTest < Test::Unit::TestCase
|
||
def setup
|
||
::Proxy::Puppet::ClassScannerFactory.new(false).reset_cache
|
||
end
|
||
|
||
def test_should_return_regular_parser
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => false)
|
||
assert_equal ::Proxy::Puppet::ClassScanner, ::Proxy::Puppet::ClassScannerFactory.new(false).scanner
|
||
end
|
||
|
||
def test_should_return_future_parser
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => false)
|
||
assert_equal ::Proxy::Puppet::ClassScannerEParser, ::Proxy::Puppet::ClassScannerFactory.new(true).scanner
|
||
end
|
||
|
||
def test_should_return_caching_parser
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => true)
|
||
scanner = ::Proxy::Puppet::ClassScannerFactory.new(false).scanner
|
||
|
||
assert_instance_of ::Proxy::Puppet::PuppetCache, scanner
|
||
assert_equal ::Proxy::Puppet::ClassScanner, scanner.class_scanner
|
||
end
|
||
|
||
def test_should_return_caching_future_parser
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => true)
|
||
scanner = ::Proxy::Puppet::ClassScannerFactory.new(true).scanner
|
||
|
||
assert scanner.is_a?(::Proxy::Puppet::PuppetCache)
|
||
assert_equal ::Proxy::Puppet::ClassScannerEParser, scanner.class_scanner
|
||
end
|
||
|
||
def test_should_use_shared_cache_by_default
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => true)
|
||
scanner1 = ::Proxy::Puppet::ClassScannerFactory.new(true).scanner
|
||
scanner2 = ::Proxy::Puppet::ClassScannerFactory.new(true).scanner
|
||
|
||
assert_equal scanner1, scanner2
|
||
end
|
||
end
|
test/puppet/class_scanner_test.rb | ||
---|---|---|
assert klasses.empty?
|
||
end
|
||
|
||
def test_should_scan_a_dir_with_cache
|
||
Proxy::Puppet::Plugin.load_test_settings(:use_cache => true)
|
||
Proxy::Puppet::PuppetCache.stubs(:read_from_cache).returns('./test/fixtures/modules_include' =>
|
||
{ 'testinclude' =>
|
||
{'timestamp' => Time.now.to_i,
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('test')],
|
||
[Proxy::Puppet::PuppetClass.new('test::check::cache')]] }})
|
||
Proxy::Puppet::PuppetCache.stubs(:write_to_cache)
|
||
klasses = Proxy::Puppet::ClassScanner.scan_directory('./test/fixtures/modules_include', "example_env")
|
||
assert klasses.any? {|k| k.name == "check::cache" }
|
||
end
|
||
|
||
def test_should_extract_parameters__no_param_parenthesis
|
||
manifest = <<-EOF
|
||
class foreman::install {
|
test/puppet/memory_store_test.rb | ||
---|---|---|
require 'test_helper'
|
||
require 'puppet_proxy/memory_store'
|
||
require 'set'
|
||
|
||
class MemoryStoreTest < Test::Unit::TestCase
|
||
|
||
def setup
|
||
@store = Proxy::Puppet::MemoryStore.new
|
||
end
|
||
|
||
def test_should_return_nil_when_key_does_not_exist
|
||
assert_equal nil, @store["key"]
|
||
end
|
||
|
||
def test_should_store
|
||
@store["key"] = "value"
|
||
assert_equal "value", @store["key"]
|
||
end
|
||
|
||
def test_should_return_nil_when_hierarchical_key_does_not_exist
|
||
assert_equal nil, @store["a", "b", "c"]
|
||
end
|
||
|
||
def test_should_store_a_hierarchical_key
|
||
@store["a", "b", "c"] = "value"
|
||
assert_equal "value", @store["a", "b", "c"]
|
||
end
|
||
|
||
def test_should_return_all_values_of_arrays
|
||
@store["a", "b", "c"] = [1, 2]
|
||
@store["a", "b", "d"] = [3, 4]
|
||
@store["a", "e", "f"] = [5, 6]
|
||
|
||
assert_equal [1, 2, 3, 4, 5, 6].to_set, @store.values("a").to_set
|
||
end
|
||
|
||
def test_should_return_all_values
|
||
@store["a", "b", "c"] = 1
|
||
@store["a", "b", "d"] = 3
|
||
@store["a", "e", "f"] = 5
|
||
|
||
assert_equal [1, 3, 5].to_set, @store.values("a").to_set
|
||
end
|
||
end
|
test/puppet/puppet_cache_test.rb | ||
---|---|---|
require 'test_helper'
|
||
require 'puppet_proxy/puppet_plugin'
|
||
require 'puppet_proxy/puppet_class'
|
||
require 'puppet_proxy/class_scanner_base'
|
||
require 'puppet_proxy/puppet_cache'
|
||
require 'tmpdir'
|
||
|
||
class PuppetCacheTest < Test::Unit::TestCase
|
||
|
||
def setup
|
||
@scanner = Proxy::Puppet::ClassScannerBase.new
|
||
@scanner.stubs(:scan_manifest).returns([Proxy::Puppet::PuppetClass.new('testinclude')]).then.
|
||
returns([Proxy::Puppet::PuppetClass.new('testinclude::sub::foo')])
|
||
@classes_cache = ::Proxy::Puppet::MemoryStore.new
|
||
@timestamps = ::Proxy::Puppet::MemoryStore.new
|
||
@scanner = ::Proxy::Puppet::PuppetCache.new(::Proxy::Puppet::ClassScanner, @classes_cache, @timestamps)
|
||
end
|
||
|
||
def test_should_refresh_cache_when_dir_is_not_in_cache
|
||
timestamp = Time.new
|
||
Proxy::Puppet::PuppetCache.expects(:read_from_cache).returns({})
|
||
Proxy::Puppet::PuppetCache.expects(:write_to_cache).with(
|
||
{"./test/fixtures/modules_include" => {
|
||
"testinclude" => {
|
||
'timestamp' => timestamp.to_i,
|
||
'manifest' => [
|
||
[::Proxy::Puppet::PuppetClass.new('testinclude')],
|
||
[::Proxy::Puppet::PuppetClass.new('testinclude::sub::foo')]]}
|
||
}}, "example_env")
|
||
Time.expects(:new).returns(timestamp)
|
||
|
||
cache = Proxy::Puppet::PuppetCache.scan_directory_with_cache('./test/fixtures/modules_include', 'example_env', @scanner)
|
||
def test_should_refresh_classes_cache_when_dir_is_not_in_cache
|
||
@scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
|
||
assert_kind_of Array, cache
|
||
assert_equal 2, cache.size
|
||
assert_equal Proxy::Puppet::PuppetClass.new('testinclude'),
|
||
@classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'].first
|
||
assert_equal Proxy::Puppet::PuppetClass.new('testinclude::sub::foo', 'param1' => 'first_parameter', 'param2' => 'second_parameter'),
|
||
@classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/sub/foo.pp'].first
|
||
assert_equal 2, @classes_cache.values('./test/fixtures/modules_include').size
|
||
end
|
||
|
||
klass = cache.find { |k| k.name == "sub::foo" }
|
||
assert cache
|
||
assert_equal "testinclude", klass.module
|
||
def test_should_refresh_timestamps_when_dir_is_not_in_cache
|
||
@scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
|
||
klass = cache.find { |k| k.name == "testinclude" }
|
||
assert klass
|
||
assert @timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/sub/foo.pp']
|
||
assert @timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp']
|
||
assert_equal 2, @timestamps.values('./test/fixtures/modules_include').size
|
||
end
|
||
|
||
def test_should_refresh_cache_when_dir_is_changed
|
||
mtime = File.mtime(Dir.glob('./test/fixtures/modules_include/*')[0]).to_i
|
||
timestamp = Time.new
|
||
|
||
Proxy::Puppet::PuppetCache.stubs(:read_from_cache).returns('./test/fixtures/modules_include' =>
|
||
{ 'testinclude' => { 'timestamp' => (mtime - 1000),
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('test')],
|
||
[Proxy::Puppet::PuppetClass.new('test::sub::foo')]] }})
|
||
Proxy::Puppet::PuppetCache.expects(:write_to_cache).with(
|
||
{"./test/fixtures/modules_include" => {
|
||
"testinclude" => {
|
||
'timestamp' => timestamp.to_i,
|
||
'manifest' => [
|
||
[::Proxy::Puppet::PuppetClass.new('testinclude')],
|
||
[::Proxy::Puppet::PuppetClass.new('testinclude::sub::foo')]]}
|
||
}}, "example_env")
|
||
Time.expects(:new).returns(timestamp)
|
||
|
||
cache = Proxy::Puppet::PuppetCache.scan_directory_with_cache('./test/fixtures/modules_include', 'example_env', @scanner)
|
||
def test_scan_directory_response
|
||
cache = @scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
|
||
assert_kind_of Array, cache
|
||
assert_equal 2, cache.size
|
||
|
||
klass = cache.find { |k| k.name == "sub::foo" }
|
||
assert cache
|
||
assert_equal "testinclude", klass.module
|
||
|
||
klass = cache.find { |k| k.name == "testinclude" }
|
||
assert klass
|
||
end
|
||
|
||
def test_cache_file_should_contain_version
|
||
Dir.mktmpdir do |cache_dir|
|
||
Proxy::Puppet::Plugin.load_test_settings(:cache_location => cache_dir)
|
||
Proxy::Puppet::PuppetCache.write_to_cache({'./test/fixtures/modules_include' => {}}, 'production')
|
||
assert File.read(File.expand_path("cache_production.json", cache_dir)).include?("\"version\":\"#{Proxy::Puppet::Plugin.version}\"")
|
||
end
|
||
assert_equal "sub::foo", klass.name
|
||
assert_equal({'param1' => 'first_parameter', 'param2' => 'second_parameter'}, klass.params)
|
||
assert cache.find { |k| k.name == "testinclude" }
|
||
end
|
||
|
||
def test_should_return_empty_hash_when_cache_version_is_mismatched
|
||
Dir.mktmpdir do |cache_dir|
|
||
Proxy::Puppet::Plugin.load_test_settings(:cache_location => cache_dir)
|
||
Proxy::Puppet::PuppetCache.write_to_cache({'./test/fixtures/modules_include' =>
|
||
{ 'testinclude' => { 'timestamp' => Time.now.to_i,
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('test')]] }}}, 'production')
|
||
|
||
Proxy::Puppet::Plugin.expects(:version).returns("0.0.0.0.1")
|
||
assert_equal({}, Proxy::Puppet::PuppetCache.read_from_cache('production'))
|
||
end
|
||
def test_should_refresh_cache_when_dir_is_changed
|
||
@classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] =
|
||
[Proxy::Puppet::PuppetClass.new('testinclude'),
|
||
Proxy::Puppet::PuppetClass.new('another_testinclude'),
|
||
Proxy::Puppet::PuppetClass.new('yet_another_testinclude')]
|
||
@timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] =
|
||
1000
|
||
assert_equal 3, @classes_cache.values('./test/fixtures/modules_include').size
|
||
|
||
@scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
|
||
assert_equal 2, @classes_cache.values('./test/fixtures/modules_include').size
|
||
assert_equal 2, @timestamps.values('./test/fixtures/modules_include').size
|
||
assert @timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] != 1000
|
||
end
|
||
|
||
def test_should_not_refresh_cache_when_cache_is_more_recent
|
||
Proxy::Puppet::PuppetCache.stubs(:read_from_cache).returns('./test/fixtures/modules_include' =>
|
||
{ 'testinclude' => { 'timestamp' => Time.now.to_i,
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('test')],
|
||
[Proxy::Puppet::PuppetClass.new('test::sub::foo')]] }})
|
||
Proxy::Puppet::PuppetCache.expects(:write_to_cache).never
|
||
cache = Proxy::Puppet::PuppetCache.scan_directory_with_cache('./test/fixtures/modules_include', 'example_env', @scanner)
|
||
def test_should_detect_module_removals
|
||
@classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/removed_testinclude/manifests/init.pp'] =
|
||
[Proxy::Puppet::PuppetClass.new('testinclude')]
|
||
@timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/removed_testinclude/manifests/init.pp'] =
|
||
Time.now.to_i + 10_000
|
||
assert @classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/removed_testinclude/manifests/init.pp']
|
||
|
||
assert_kind_of Array, cache
|
||
# reading from the cache returns two puppet classes
|
||
assert_equal 2, cache.size
|
||
@scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
|
||
klass = cache.find { |k| k.name == "sub::foo" }
|
||
assert cache
|
||
assert_equal "test", klass.module
|
||
assert_nil @classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/removed_testinclude/manifests/init.pp']
|
||
assert_nil @timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/removed_testinclude/manifests/init.pp']
|
||
assert @classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp']
|
||
assert @classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/sub/foo.pp']
|
||
end
|
||
|
||
klass = cache.find { |k| k.name == "test" }
|
||
assert klass
|
||
def test_should_not_refresh_cache_when_cache_is_more_recent
|
||
@classes_cache['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] =
|
||
[Proxy::Puppet::PuppetClass.new('testinclude'),
|
||
Proxy::Puppet::PuppetClass.new('another_testinclude'),
|
||
Proxy::Puppet::PuppetClass.new('yet_another_testinclude')]
|
||
@timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] =
|
||
(current_time = Time.now.to_i + 10_000)
|
||
assert_equal 3, @classes_cache.values('./test/fixtures/modules_include').size
|
||
|
||
@scanner.scan_directory('./test/fixtures/modules_include', 'example_env')
|
||
assert_equal 4, @classes_cache.values('./test/fixtures/modules_include').size
|
||
assert_equal 2, @timestamps.values('./test/fixtures/modules_include').size
|
||
assert @timestamps['./test/fixtures/modules_include', './test/fixtures/modules_include/testinclude/manifests/init.pp'] == current_time
|
||
end
|
||
|
||
def test_read_write_cache_idempotency
|
||
Dir.mktmpdir do |cache_dir|
|
||
Proxy::Puppet::Plugin.load_test_settings(:cache_location => cache_dir)
|
||
|
||
expected = {'./test/fixtures/modules_include' =>
|
||
{'testinclude' => { 'timestamp' => Time.now.to_i,
|
||
'manifest' => [[Proxy::Puppet::PuppetClass.new('test')],
|
||
[Proxy::Puppet::PuppetClass.new('test::sub::foo')]] }}}
|
||
Proxy::Puppet::PuppetCache.write_to_cache(expected, 'production')
|
||
assert_equal expected, Proxy::Puppet::PuppetCache.read_from_cache('production')
|
||
end
|
||
def test_should_return_no_puppet_classes_when_environment_has_no_modules
|
||
Dir.expects(:glob).with('empty_environment/*').returns([])
|
||
result = @scanner.scan_directory('empty_environment', 'example_env')
|
||
|
||
assert result.empty?
|
||
end
|
||
end
|
test/puppet/puppet_class_test.rb | ||
---|---|---|
assert_equal "klass::nested", klass.name
|
||
end
|
||
|
||
def test_scan_directory_loads_scanner
|
||
Proxy::Puppet::Initializer.expects(:load)
|
||
Proxy::Puppet::ClassScanner.expects(:scan_directory).with('/foo', 'development')
|
||
Proxy::Puppet::PuppetClass.scan_directory('/foo', 'development', nil)
|
||
end
|
||
|
||
def test_scan_directory_loads_eparser_scanner
|
||
return unless Puppet::PUPPETVERSION.to_f >= 3.2
|
||
Proxy::Puppet::Initializer.expects(:load)
|
||
Proxy::Puppet::ClassScannerEParser.expects(:scan_directory).with('/foo', 'development')
|
||
Proxy::Puppet::PuppetClass.scan_directory('/foo', 'development', true)
|
||
end
|
||
|
||
def test_json_serialization
|
||
clazz = Proxy::Puppet::PuppetClass.new(
|
||
"foreman_proxy::install", "namedconf_path"=>"${::dns::params::namedconf_path}", "dnsdir"=>"${::dns::params::dnsdir}")
|
test/puppet/puppet_environment_test.rb | ||
---|---|---|
def test_classes_calls_scan_directory
|
||
Proxy::Puppet::ConfigReader.any_instance.stubs(:get).returns({})
|
||
env = Proxy::Puppet::Environment.new(:name => 'production', :paths => ['/etc/puppet/modules', '/etc/puppet/production'])
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/modules', 'production', nil)
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/production', 'production', nil)
|
||
::Proxy::Puppet::ClassScanner.expects(:scan_directory).with('/etc/puppet/modules', 'production')
|
||
::Proxy::Puppet::ClassScanner.expects(:scan_directory).with('/etc/puppet/production', 'production')
|
||
env.classes
|
||
end
|
||
|
||
def test_classes_calls_scan_directory_with_eparser_master
|
||
Proxy::Puppet::ConfigReader.any_instance.stubs(:get).returns(:master => {:parser => 'future'})
|
||
env = Proxy::Puppet::Environment.new(:name => 'production', :paths => ['/etc/puppet/modules', '/etc/puppet/production'])
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/modules', 'production', true)
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/production', 'production', true)
|
||
Proxy::Puppet::ClassScannerEParser.expects(:scan_directory).with('/etc/puppet/modules', 'production')
|
||
Proxy::Puppet::ClassScannerEParser.expects(:scan_directory).with('/etc/puppet/production', 'production')
|
||
env.classes
|
||
end
|
||
|
||
def test_classes_calls_scan_directory_with_eparser_main
|
||
Proxy::Puppet::ConfigReader.any_instance.stubs(:get).returns(:main => {:parser => 'future'})
|
||
env = Proxy::Puppet::Environment.new(:name => 'production', :paths => ['/etc/puppet/modules', '/etc/puppet/production'])
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/modules', 'production', true)
|
||
Proxy::Puppet::PuppetClass.expects(:scan_directory).with('/etc/puppet/production', 'production', true)
|
||
Proxy::Puppet::ClassScannerEParser.expects(:scan_directory).with('/etc/puppet/modules', 'production')
|
||
Proxy::Puppet::ClassScannerEParser.expects(:scan_directory).with('/etc/puppet/production', 'production')
|
||
env.classes
|
||
end
|
||
|
test/puppet/testing_class_scanner_factory.rb | ||
---|---|---|
require 'puppet_proxy/class_scanner_factory'
|
||
|
||
class ::Proxy::Puppet::ClassScannerFactory
|
||
def reset_cache; @@cached = nil; end
|
||
end
|
Also available in: Unified diff
Fixes #11229: changes in puppet modules are now being detected when listing available puppet classes