Project

General

Profile

Download (3.65 KB) Statistics
| Branch: | Tag: | Revision:
require 'json'

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}")

cache = read_from_cache(environment)

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)

if File.exist?(cachefile)
as_hash = JSON.load(File.new(cachefile))

if as_hash.delete('version') != ::Proxy::Puppet::Plugin.version
logger.info("Mismatching puppet cache version, discarding.")
return {}
end

# 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)] }
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)

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
end
end
end
end
(13-13/19)