Project

General

Profile

« Previous | Next » 

Revision af58b9f1

Added by Rickard von Essen over 10 years ago

fixes #2878 - Import Classes when using parser = future, on Puppet 3.2+

View differences:

lib/proxy/puppet/puppet_class.rb
require 'proxy/puppet/initializer'
require 'proxy/puppet/class_scanner'
require 'proxy/puppet/class_scanner_eparser'
module Proxy::Puppet
......
class << self
# scans a given directory and its sub directory for puppet classes
# returns an array of PuppetClass objects.
def scan_directory directory
def scan_directory directory, eparser = false
# Get a Puppet Parser to parse the manifest source
Initializer.load
parser = Puppet::Parser::Parser.new Puppet::Node::Environment.new
Dir.glob("#{directory}/*/manifests/**/*.pp").map do |filename|
scan_manifest File.read(filename), filename, parser
end.compact.flatten
end
def scan_manifest manifest, filename = '', parser = nil
klasses = []
# Get a Puppet Parser to parse the manifest source
unless parser
Initializer.load
parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
end
already_seen = Set.new parser.known_resource_types.hostclasses.keys
already_seen << '' # Prevent the toplevel "main" class from matching
ast = parser.parse manifest
# Get the parsed representation of the top most objects
hostclasses = ast.respond_to?(:instantiate) ? ast.instantiate('') : ast.hostclasses.values
hostclasses.each do |klass|
# Only look at classes
if klass.type == :hostclass and not already_seen.include? klass.namespace
params = {}
# Get parameters and eventual default values
klass.arguments.each do |name, value|
params[name] = ast_to_value(value) rescue nil
end
klasses << new(klass.namespace, params)
end
end
klasses
rescue => e
puts "Error while parsing #{filename}: #{e}"
klasses
end
private
def ast_to_value value
unless value.class.name.start_with? "Puppet::Parser::AST::"
# Native Ruby types
case value
# Supported with exact JSON equivalent
when NilClass, String, Numeric, Array, Hash, FalseClass, TrueClass
value
when Struct
value.hash
when Enumerable
value.to_a
# Stringified
when Regexp # /(?:stringified)/
"/#{value.to_s}/"
when Symbol # stringified
value.to_s
else
raise TypeError
end
if eparser
ClassScannerEParser.scan_directory directory
else
# Parser types
case value
# Supported with exact JSON equivalent
when Puppet::Parser::AST::Boolean, Puppet::Parser::AST::String
value.evaluate nil
# Supported with stringification
when Puppet::Parser::AST::Concat
# This is the case when two params are concatenated together ,e.g. "param_${key}_something"
# Note1: only simple content are supported, plus variables whose raw name is taken
# Note2: The variable substitution WON'T be done by Puppet from the ENC YAML output
value.value.map do |v|
case v
when Puppet::Parser::AST::String
v.evaluate nil
when Puppet::Parser::AST::Variable
"${#{v.value}}"
else
raise TypeError
end
end.join rescue nil
when Puppet::Parser::AST::Variable
"${#{value}}"
when Puppet::Parser::AST::Type
value.value
when Puppet::Parser::AST::Name
(Puppet::Parser::Scope.number?(value.value) or value.value)
when Puppet::Parser::AST::Undef # equivalent of nil, but optional
""
# Depends on content
when Puppet::Parser::AST::ASTArray
value.inject([]) { |arr, v| (arr << ast_to_value(v)) rescue arr }
when Puppet::Parser::AST::ASTHash
Hash[value.value.each.inject([]) { |arr, (k,v)| (arr << [ast_to_value(k), ast_to_value(v)]) rescue arr }]
when Puppet::Parser::AST::Function
value.to_s
# Let's see if a raw evaluation works with no scope for any other type
else
if value.respond_to? :evaluate
# Can probably work for: (depending on the actual content)
# - Puppet::Parser::AST::ArithmeticOperator
# - Puppet::Parser::AST::ComparisonOperator
# - Puppet::Parser::AST::BooleanOperator
# - Puppet::Parser::AST::Minus
# - Puppet::Parser::AST::Not
# May work for:
# - Puppet::Parser::AST::InOperator
# - Puppet::Parser::AST::MatchOperator
# - Puppet::Parser::AST::Selector
# Probably won't work for
# - Puppet::Parser::AST::Variable
# - Puppet::Parser::AST::HashOrArrayAccess
# - Puppet::Parser::AST::ResourceReference
value.evaluate nil
else
raise TypeError
end
end
ClassScanner.scan_directory directory
end
end
end
def initialize name, params = {}
......
end
end

Also available in: Unified diff