From 49059568d0e4e00bbc35d6f9b2a6cd23e7d00f46 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Wed, 16 Mar 2011 14:26:04 -0500 Subject: (5909) Function to dyncamically generate resources. This function allows you to dynamically generate resources, passing them as a hash to the create_resources function. This was originally written to be used together with an ENC. Resources can be programitally generated as yaml and passed to a class. classes: webserver::instances: instances: instance1: foo: bar instance2: foo: blah Then puppet code can consume the hash parameters and convert then into resources class webserver::instances ( $instances = {} ) { create_resources('webserver::instance', $instances) } Now I can dynamically determine how webserver instances are deployed to nodes by updating the YAML files. --- lib/puppet/parser/functions/create_resources.rb | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 lib/puppet/parser/functions/create_resources.rb (limited to 'lib/puppet/parser') diff --git a/lib/puppet/parser/functions/create_resources.rb b/lib/puppet/parser/functions/create_resources.rb new file mode 100644 index 000000000..430f110b4 --- /dev/null +++ b/lib/puppet/parser/functions/create_resources.rb @@ -0,0 +1,47 @@ +Puppet::Parser::Functions::newfunction(:create_resources, :doc => ' +Converts a hash into a set of resources and adds them to the catalog. +Takes two parameters: + create_resource($type, $resources) + Creates resources of type $type from the $resources hash. Assumes that + hash is in the following form: + {title=>{parameters}} + This is currently tested for defined resources, classes, as well as native types +') do |args| + raise ArgumentError, ("create_resources(): wrong number of arguments (#{args.length}; must be 2)") if args.length != 2 + #raise ArgumentError, 'requires resource type and param hash' if args.size < 2 + # figure out what kind of resource we are + type_of_resource = nil + type_name = args[0].downcase + if type_name == 'class' + type_of_resource = :class + else + if resource = Puppet::Type.type(type_name.to_sym) + type_of_resource = :type + elsif resource = find_definition(type_name.downcase) + type_of_resource = :define + else + raise ArgumentError, "could not create resource of unknown type #{type_name}" + end + end + # iterate through the resources to create + args[1].each do |title, params| + raise ArgumentError, 'params should not contain title' if(params['title']) + case type_of_resource + when :type + res = resource.hash2resource(params.merge(:title => title)) + catalog.add_resource(res) + when :define + p_resource = Puppet::Parser::Resource.new(type_name, title, :scope => self, :source => resource) + params.merge(:name => title).each do |k,v| + p_resource.set_parameter(k,v) + end + resource.instantiate_resource(self, p_resource) + compiler.add_resource(self, p_resource) + when :class + klass = find_hostclass(title) + raise ArgumentError, "could not find hostclass #{title}" unless klass + klass.ensure_in_catalog(self, params) + compiler.catalog.add_class([title]) + end + end +end -- cgit From 8124f8e725148be2556285629171d4964973c424 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Thu, 24 Mar 2011 16:56:19 -0700 Subject: (#4576) Raise an error when a node is classified into a non-existent class In 2.6.x, this was upgraded from "info" to "warning". This change for Statler escalates the warning to an exception which will abort the compile. This makes compiling fail consistently when you try to use an undefined class from any of: node classifiers, the class keyword, and the include function. Paired-with: Jacob Helwig --- lib/puppet/parser/compiler.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'lib/puppet/parser') diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb index fdabd05c9..a891f1a11 100644 --- a/lib/puppet/parser/compiler.rb +++ b/lib/puppet/parser/compiler.rb @@ -20,7 +20,7 @@ class Puppet::Parser::Compiler puts detail.backtrace if Puppet[:trace] raise Puppet::Error, "#{detail} on node #{node.name}" ensure - # We get these from the environment and only cache them in a thread + # We get these from the environment and only cache them in a thread # variable for the duration of the compilation. Thread.current[:known_resource_types] = nil Thread.current[:env_module_directories] = nil @@ -133,12 +133,11 @@ class Puppet::Parser::Compiler end # Evaluate each specified class in turn. If there are any classes we can't - # find, just tag the catalog and move on. This method really just - # creates resource objects that point back to the classes, and then the - # resources are themselves evaluated later in the process. + # find, raise an error. This method really just creates resource objects + # that point back to the classes, and then the resources are themselves + # evaluated later in the process. def evaluate_classes(classes, scope, lazy_evaluate = true) raise Puppet::DevError, "No source for scope passed to evaluate_classes" unless scope.source - found = [] param_classes = nil # if we are a param class, save the classes hash # and transform classes to be the keys @@ -153,20 +152,17 @@ class Puppet::Parser::Compiler if param_classes resource = klass.ensure_in_catalog(scope, param_classes[name] || {}) else - found << name and next if scope.class_scope(klass) + next if scope.class_scope(klass) resource = klass.ensure_in_catalog(scope) end # If they've disabled lazy evaluation (which the :include function does), # then evaluate our resource immediately. resource.evaluate unless lazy_evaluate - found << name else - Puppet.info "Could not find class #{name} for #{node.name}" - @catalog.tag(name) + raise Puppet::Error, "Could not find class #{name} for #{node.name}" end end - found end def evaluate_relationships -- cgit From e16a38349c596c4a6ea682173e0cc704dedc98a7 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 25 Mar 2011 14:15:12 -0700 Subject: Fixing #6851 - ResourceType#find/search loads types Previously we could only find types from site.pp, but we now automatically load the specified type (for find) or all types. This also adds a TypeLoader#import_all capable of importing all manifests (ruby or puppet) on a given system. Signed-off-by: Luke Kanies Reviewed-by: Daniel Pittman --- lib/puppet/parser/type_loader.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'lib/puppet/parser') diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb index 140c9f2ca..1fba73d0b 100644 --- a/lib/puppet/parser/type_loader.rb +++ b/lib/puppet/parser/type_loader.rb @@ -92,6 +92,34 @@ class Puppet::Parser::TypeLoader end end + def import_all + require 'find' + + module_names = [] + # Collect the list of all known modules + environment.modulepath.each do |path| + Dir.chdir(path) do + Dir.glob("*").each do |dir| + next unless FileTest.directory?(dir) + module_names << dir + end + end + end + + module_names.uniq! + # And then load all files from each module, but (relying on system + # behavior) only load files from the first module of a given name. E.g., + # given first/foo and second/foo, only files from first/foo will be loaded. + module_names.each do |name| + mod = Puppet::Module.new(name, environment) + Find.find(File.join(mod.path, "manifests")) do |path| + if path =~ /\.pp$/ or path =~ /\.rb$/ + import(path) + end + end + end + end + def known_resource_types environment.known_resource_types end -- cgit From daaa048a8d8829ad509b4a456826cc8a33cf6444 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Thu, 24 Mar 2011 17:51:59 -0700 Subject: (#5477) Allow watch_file to watch non-existent files, especially site.pp The watch_file mechanism would refuse to monitor paths to files that didn't exist. This patch makes it possible to watch a file that hasn't been created yet, so when it is created, you manifests will get reparsed. Paired-With: Max Martin Reviewed-By: Jacob Helwig --- lib/puppet/parser/lexer.rb | 5 +++-- lib/puppet/parser/parser_support.rb | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/puppet/parser') diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb index 4050adeb8..2f416615e 100644 --- a/lib/puppet/parser/lexer.rb +++ b/lib/puppet/parser/lexer.rb @@ -312,7 +312,8 @@ class Puppet::Parser::Lexer def file=(file) @file = file @line = 1 - @scanner = StringScanner.new(File.read(file)) + contents = File.exists?(file) ? File.read(file) : "" + @scanner = StringScanner.new(contents) end def shift_token @@ -547,7 +548,7 @@ class Puppet::Parser::Lexer value,terminator = slurpstring('"$') token_queue << [TOKENS[token_type[terminator]],preamble+value] if terminator != '$' or @scanner.scan(/\{/) - token_queue.shift + token_queue.shift elsif var_name = @scanner.scan(%r{(\w*::)*\w+|[0-9]}) token_queue << [TOKENS[:VARIABLE],var_name] tokenize_interpolated_string(DQ_continuation_token_types) diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index 746aa0f90..7888fe1dc 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -79,7 +79,6 @@ class Puppet::Parser::Parser unless file =~ /\.pp$/ file = file + ".pp" end - raise Puppet::Error, "Could not find file #{file}" unless FileTest.exist?(file) end raise Puppet::AlreadyImportedError, "Import loop detected" if known_resource_types.watching_file?(file) -- cgit From ade4efea6d2d4dbee7ccfec62114df0c5dcf33e2 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Mon, 28 Mar 2011 11:52:11 -0700 Subject: (#6830) Fix MD5 handling to work with Ruby 1.9 In Ruby 1.9 you have to require 'digest/md5' instead of just 'md5'. The following irb sessions from each version of Ruby should explain the changes in how MD5 is used between Ruby versions and why this patch was made. ruby-1.9.2-p136 :001 > require 'md5' LoadError: no such file to load -- md5 ruby-1.9.2-p136 :002 > require 'digest/md5' => true ruby-1.9.2-p136 :003 > Digest::MD5.hexdigest('mystring') => "169319501261c644a58610f967e8f9d0" ruby-1.9.2-p136 :004 > Digest::MD5.new('mystring') => # ruby-1.8.7-p330 :001 > require 'digest/md5' => [] ruby-1.8.7-p330 :002 > require 'md5' => ["MD5"] ruby-1.8.7-p330 :003 > Digest::MD5.hexdigest('mystring') => "169319501261c644a58610f967e8f9d0" ruby-1.8.7-p330 :004 > MD5.new('mystring') => # ruby-1.8.7-p330 :005 > MD5.new('mystring').to_s => "169319501261c644a58610f967e8f9d0" ruby-1.8.7-p330 :006 > Digest::MD5.new('mystring') ArgumentError: wrong number of arguments (1 for 0) Reviewed-by: Jesse Wolfe --- lib/puppet/parser/functions/fqdn_rand.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/puppet/parser') diff --git a/lib/puppet/parser/functions/fqdn_rand.rb b/lib/puppet/parser/functions/fqdn_rand.rb index 52946f2c1..91157a148 100644 --- a/lib/puppet/parser/functions/fqdn_rand.rb +++ b/lib/puppet/parser/functions/fqdn_rand.rb @@ -5,8 +5,8 @@ Puppet::Parser::Functions::newfunction(:fqdn_rand, :type => :rvalue, :doc => $random_number = fqdn_rand(30) $random_number_seed = fqdn_rand(30,30)") do |args| - require 'md5' + require 'digest/md5' max = args.shift - srand MD5.new([lookupvar('fqdn'),args].join(':')).to_s.hex + srand(Digest::MD5.hexdigest([lookupvar('fqdn'),args].join(':')).hex) rand(max).to_s end -- cgit