From 3c4412128a50e41380108e5a90f2656329b84492 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Wed, 8 Sep 2010 11:31:00 -0700 Subject: [#4590] SimpleGraph is slow Rewrote SimpleGraph to use a more efficient internal representation. To preserve compatibility with older clients, graphs are still serialized to YAML using the format used by Puppet 2.6. However, a newer, more compact format can be enabled by setting "use_new_yaml_format" to true. Deserialization from YAML accepts either the old 2.6 format or the newer format. In a later release, once we no longer need to be compatible with 2.6, we will be able to switch to the new format. To make deserialization accept multiple formats, it was necessary to use the yaml_initialize method. This method is not supported in versions of Ruby prior to 1.8.3, so a monkey patch is included to add support for it to Ruby 1.8.1 and 1.8.2. Thanks to Markus Roberts for the SimpleGraph rewrite. Thanks to Jesse Wolfe for figuring out how to write the yaml_initialize monkey patch. --- lib/puppet/simple_graph.rb | 417 +++++++++++++++++++------------------- lib/puppet/util/monkey_patches.rb | 13 ++ 2 files changed, 222 insertions(+), 208 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb index 55b39fadf..6d153b46d 100644 --- a/lib/puppet/simple_graph.rb +++ b/lib/puppet/simple_graph.rb @@ -7,123 +7,45 @@ require 'set' # A hopefully-faster graph class to replace the use of GRATR. class Puppet::SimpleGraph - # An internal class for handling a vertex's edges. - class VertexWrapper - attr_accessor :in, :out, :vertex - - # Remove all references to everything. - def clear - @adjacencies[:in].clear - @adjacencies[:out].clear - @vertex = nil - end - - def initialize(vertex) - @vertex = vertex - @adjacencies = {:in => {}, :out => {}} - end - - # Find adjacent vertices or edges. - def adjacent(options) - direction = options[:direction] || :out - options[:type] ||= :vertices - - return send(direction.to_s + "_edges") if options[:type] == :edges - - @adjacencies[direction].keys.reject { |vertex| @adjacencies[direction][vertex].empty? } - end - - # Add an edge to our list. - def add_edge(direction, edge) - opposite_adjacencies(direction, edge) << edge - end - - # Return all known edges. - def edges - in_edges + out_edges - end - - # Test whether we share an edge with a given vertex. - def has_edge?(direction, vertex) - return(vertex_adjacencies(direction, vertex).length > 0 ? true : false) - end - - # Create methods for returning the degree and edges. - [:in, :out].each do |direction| - # LAK:NOTE If you decide to create methods for directly - # testing the degree, you'll have to get the values and flatten - # the results -- you might have duplicate edges, which can give - # a false impression of what the degree is. That's just - # as expensive as just getting the edge list, so I've decided - # to only add this method. - define_method("#{direction}_edges") do - @adjacencies[direction].values.inject([]) { |total, adjacent| total += adjacent.to_a; total } - end - end - - # The other vertex in the edge. - def other_vertex(direction, edge) - case direction - when :in; edge.source - else - edge.target - end - end - - # Remove an edge from our list. Assumes that we've already checked - # that the edge is valid. - def remove_edge(direction, edge) - opposite_adjacencies(direction, edge).delete(edge) - end - - def to_s - vertex.to_s - end - - private - - # These methods exist so we don't need a Hash with a default proc. - - # Look up the adjacencies for a vertex at the other end of an - # edge. - def opposite_adjacencies(direction, edge) - opposite_vertex = other_vertex(direction, edge) - vertex_adjacencies(direction, opposite_vertex) - end - - # Look up the adjacencies for a given vertex. - def vertex_adjacencies(direction, vertex) - @adjacencies[direction][vertex] ||= Set.new - @adjacencies[direction][vertex] - end - end - + # + # All public methods of this class must maintain (assume ^ ensure) the following invariants, where "=~=" means + # equiv. up to order: + # + # @in_to.keys =~= @out_to.keys =~= all vertices + # @in_to.values.collect { |x| x.values }.flatten =~= @out_from.values.collect { |x| x.values }.flatten =~= all edges + # @in_to[v1][v2] =~= @out_from[v2][v1] =~= all edges from v1 to v2 + # @in_to [v].keys =~= vertices with edges leading to v + # @out_from[v].keys =~= vertices with edges leading from v + # no operation may shed reference loops (for gc) + # recursive operation must scale with the depth of the spanning trees, or better (e.g. no recursion over the set + # of all vertices, etc.) + # + # This class is intended to be used with DAGs. However, if the + # graph has a cycle, it will not cause non-termination of any of the + # algorithms. The topsort method detects and reports cycles. + # def initialize - @vertices = {} - @edges = [] + @in_to = {} + @out_from = {} + @upstream_from = {} + @downstream_from = {} end # Clear our graph. def clear - @vertices.each { |vertex, wrapper| wrapper.clear } - @vertices.clear - @edges.clear - end - - # Which resources a given resource depends upon. - def dependents(resource) - tree_from_vertex(resource).keys + @in_to.clear + @out_from.clear + @upstream_from.clear + @downstream_from.clear end # Which resources depend upon the given resource. def dependencies(resource) - # Cache the reversal graph, because it's somewhat expensive - # to create. - @reversal ||= reversal - # Strangely, it's significantly faster to search a reversed - # tree in the :out direction than to search a normal tree - # in the :in direction. - @reversal.tree_from_vertex(resource, :out).keys + vertex?(resource) ? upstream_from_vertex(resource).keys : [] + end + + def dependents(resource) + vertex?(resource) ? downstream_from_vertex(resource).keys : [] end # Whether our graph is directed. Always true. Used to produce dot files. @@ -133,8 +55,7 @@ class Puppet::SimpleGraph # Determine all of the leaf nodes below a given vertex. def leaves(vertex, direction = :out) - tree = tree_from_vertex(vertex, direction) - l = tree.keys.find_all { |c| adjacent(c, :direction => direction).empty? } + tree_from_vertex(vertex, direction).keys.find_all { |c| adjacent(c, :direction => direction).empty? } end # Collect all of the edges that the passed events match. Returns @@ -149,9 +70,7 @@ class Puppet::SimpleGraph # Get all of the edges that this vertex should forward events # to, which is the same thing as saying all edges directly below # This vertex in the graph. - adjacent(source, :direction => :out, :type => :edges).find_all do |edge| - edge.match?(event.name) - end + @out_from[source].values.flatten.find_all { |edge| edge.match?(event.name) } end # Return a reversed version of this graph. @@ -159,20 +78,50 @@ class Puppet::SimpleGraph result = self.class.new vertices.each { |vertex| result.add_vertex(vertex) } edges.each do |edge| - newedge = edge.class.new(edge.target, edge.source, edge.label) - result.add_edge(newedge) + result.add_edge edge.class.new(edge.target, edge.source, edge.label) end result end # Return the size of the graph. def size - @vertices.length + vertices.size end - # Return the graph as an array. def to_a - @vertices.keys + vertices + end + + # Provide a topological sort with cycle reporting + def topsort_with_cycles + degree = {} + zeros = [] + result = [] + + # Collect each of our vertices, with the number of in-edges each has. + vertices.each do |v| + edges = @in_to[v].dup + zeros << v if edges.empty? + degree[v] = edges + end + + # Iterate over each 0-degree vertex, decrementing the degree of + # each of its out-edges. + while v = zeros.pop + result << v + @out_from[v].each { |v2,es| + degree[v2].delete(v) + zeros << v2 if degree[v2].empty? + } + end + + # If we have any vertices left with non-zero in-degrees, then we've found a cycle. + if cycles = degree.values.reject { |ns| ns.empty? } and cycles.length > 0 + message = cycles.collect { |edges| '('+edges.collect { |e| e.to_s }.join(", ")+')' }.join(", ") + raise Puppet::Error, "Found dependency cycles in the following relationships: #{message}; try using the '--graph' option and open the '.dot' files in OmniGraffle or GraphViz" + end + + result end # Provide a topological sort. @@ -182,26 +131,24 @@ class Puppet::SimpleGraph result = [] # Collect each of our vertices, with the number of in-edges each has. - @vertices.each do |name, wrapper| - edges = wrapper.in_edges - zeros << wrapper if edges.length == 0 - degree[wrapper.vertex] = edges + vertices.each do |v| + edges = @in_to[v] + zeros << v if edges.empty? + degree[v] = edges.length end # Iterate over each 0-degree vertex, decrementing the degree of # each of its out-edges. - while wrapper = zeros.pop - result << wrapper.vertex - wrapper.out_edges.each do |edge| - degree[edge.target].delete(edge) - zeros << @vertices[edge.target] if degree[edge.target].length == 0 - end + while v = zeros.pop + result << v + @out_from[v].each { |v2,es| + zeros << v2 if (degree[v2] -= 1) == 0 + } end # If we have any vertices left with non-zero in-degrees, then we've found a cycle. - if cycles = degree.find_all { |vertex, edges| edges.length > 0 } and cycles.length > 0 - message = cycles.collect { |vertex, edges| edges.collect { |e| e.to_s }.join(", ") }.join(", ") - raise Puppet::Error, "Found dependency cycles in the following relationships: #{message}; try using the '--graph' option and open the '.dot' files in OmniGraffle or GraphViz" + if cycles = degree.values.reject { |ns| ns == 0 } and cycles.length > 0 + topsort_with_cycles end result @@ -209,103 +156,80 @@ class Puppet::SimpleGraph # Add a new vertex to the graph. def add_vertex(vertex) - @reversal = nil - return false if vertex?(vertex) - setup_vertex(vertex) - true # don't return the VertexWrapper instance. + @in_to[vertex] ||= {} + @out_from[vertex] ||= {} end # Remove a vertex from the graph. - def remove_vertex!(vertex) - return nil unless vertex?(vertex) - @vertices[vertex].edges.each { |edge| remove_edge!(edge) } - @edges -= @vertices[vertex].edges - @vertices[vertex].clear - @vertices.delete(vertex) + def remove_vertex!(v) + return unless vertex?(v) + @upstream_from.clear + @downstream_from.clear + (@in_to[v].values+@out_from[v].values).flatten.each { |e| remove_edge!(e) } + @in_to.delete(v) + @out_from.delete(v) end # Test whether a given vertex is in the graph. - def vertex?(vertex) - @vertices.include?(vertex) + def vertex?(v) + @in_to.include?(v) end # Return a list of all vertices. def vertices - @vertices.keys + @in_to.keys end # Add a new edge. The graph user has to create the edge instance, # since they have to specify what kind of edge it is. - def add_edge(source, target = nil, label = nil) - @reversal = nil - if target - edge = Puppet::Relationship.new(source, target, label) - else - edge = source - end - [edge.source, edge.target].each { |vertex| setup_vertex(vertex) unless vertex?(vertex) } - @vertices[edge.source].add_edge :out, edge - @vertices[edge.target].add_edge :in, edge - @edges << edge - true + def add_edge(e,*a) + return add_relationship(e,*a) unless a.empty? + @upstream_from.clear + @downstream_from.clear + add_vertex(e.source) + add_vertex(e.target) + @in_to[ e.target][e.source] ||= []; @in_to[ e.target][e.source] |= [e] + @out_from[e.source][e.target] ||= []; @out_from[e.source][e.target] |= [e] end - # Find a matching edge. Note that this only finds the first edge, - # not all of them or whatever. - def edge(source, target) - @edges.each_with_index { |test_edge, index| return test_edge if test_edge.source == source and test_edge.target == target } + def add_relationship(source, target, label = nil) + add_edge Puppet::Relationship.new(source, target, label) end - def edge_label(source, target) - return nil unless edge = edge(source, target) - edge.label + # Find all matching edges. + def edges_between(source, target) + (@out_from[source] || {})[target] || [] end # Is there an edge between the two vertices? def edge?(source, target) - return false unless vertex?(source) and vertex?(target) - - @vertices[source].has_edge?(:out, target) + vertex?(source) and vertex?(target) and @out_from[source][target] end def edges - @edges.dup + @in_to.values.collect { |x| x.values }.flatten end - # Remove an edge from our graph. - def remove_edge!(edge) - @vertices[edge.source].remove_edge(:out, edge) - @vertices[edge.target].remove_edge(:in, edge) - - @edges.delete(edge) - nil + def each_edge + @in_to.each { |t,ns| ns.each { |s,es| es.each { |e| yield e }}} end - # Find adjacent edges. - def adjacent(vertex, options = {}) - return [] unless wrapper = @vertices[vertex] - wrapper.adjacent(options) + # Remove an edge from our graph. + def remove_edge!(e) + if edge?(e.source,e.target) + @upstream_from.clear + @downstream_from.clear + @in_to [e.target].delete e.source if (@in_to [e.target][e.source] -= [e]).empty? + @out_from[e.source].delete e.target if (@out_from[e.source][e.target] -= [e]).empty? + end end - private - - # An internal method that skips the validation, so we don't have - # duplicate validation calls. - def setup_vertex(vertex) - @vertices[vertex] = VertexWrapper.new(vertex) + # Find adjacent edges. + def adjacent(v, options = {}) + return [] unless ns = (options[:direction] == :in) ? @in_to[v] : @out_from[v] + (options[:type] == :edges) ? ns.values.flatten : ns.keys end - - public - -# # For some reason, unconnected vertices do not show up in -# # this graph. -# def to_jpg(path, name) -# gv = vertices -# Dir.chdir(path) do -# induced_subgraph(gv).write_to_graphic_file('jpg', name) -# end -# end - + # Take container information from another graph and use it # to replace any container vertices with their respective leaves. # This creates direct relationships where there were previously @@ -381,6 +305,26 @@ class Puppet::SimpleGraph predecessor end + def downstream_from_vertex(v) + return @downstream_from[v] if @downstream_from[v] + result = @downstream_from[v] = {} + @out_from[v].keys.each do |node| + result[node] = 1 + result.update(downstream_from_vertex(node)) + end + result + end + + def upstream_from_vertex(v) + return @upstream_from[v] if @upstream_from[v] + result = @upstream_from[v] = {} + @in_to[v].keys.each do |node| + result[node] = 1 + result.update(upstream_from_vertex(node)) + end + result + end + # LAK:FIXME This is just a paste of the GRATR code with slight modifications. # Return a DOT::DOTDigraph for directed graphs or a DOT::DOTSubgraph for an @@ -422,18 +366,6 @@ class Puppet::SimpleGraph system('dotty', dotfile) end - # Use +dot+ to create a graphical representation of the graph. Returns the - # filename of the graphics file. - def write_to_graphic_file (fmt='png', dotfile='graph') - src = dotfile + '.dot' - dot = dotfile + '.' + fmt - - File.open(src, 'w') {|f| f << self.to_dot << "\n"} - - system( "dot -T#{fmt} #{src} -o #{dot}" ) - dot - end - # Produce the graph files if requested. def write_graph(name) return unless Puppet[:graph] @@ -445,4 +377,73 @@ class Puppet::SimpleGraph f.puts to_dot("name" => name.to_s.capitalize) } end + + # This flag may be set to true to use the new YAML serialzation + # format (where @vertices is a simple list of vertices rather than a + # list of VertexWrapper objects). Deserialization supports both + # formats regardless of the setting of this flag. + class << self + attr_accessor :use_new_yaml_format + end + self.use_new_yaml_format = false + + # Stub class to allow graphs to be represented in YAML using the old + # (version 2.6) format. + class VertexWrapper + attr_reader :vertex, :adjacencies + def initialize(vertex, adjacencies) + @vertex = vertex + @adjacencies = adjacencies + end + end + + # instance_variable_get is used by Object.to_zaml to get instance + # variables. Override it so that we can simulate the presence of + # instance variables @edges and @vertices for serialization. + def instance_variable_get(v) + case v.to_s + when '@edges' then + edges + when '@vertices' then + if self.class.use_new_yaml_format + vertices + else + result = {} + vertices.each do |vertex| + adjacencies = {} + [:in, :out].each do |direction| + adjacencies[direction] = {} + adjacent(vertex, :direction => direction, :type => :edges).each do |edge| + other_vertex = direction == :in ? edge.source : edge.target + (adjacencies[direction][other_vertex] ||= Set.new).add(edge) + end + end + result[vertex] = Puppet::SimpleGraph::VertexWrapper.new(vertex, adjacencies) + end + result + end + else + super(v) + end + end + + def to_yaml_properties + other_vars = instance_variables.reject { |v| %w{@in_to @out_from @upstream_from @downstream_from}.include?(v) } + (other_vars + %w{@vertices @edges}).sort.uniq + end + + def yaml_initialize(tag, var) + initialize() + vertices = var.delete('vertices') + edges = var.delete('edges') + if vertices.is_a?(Hash) + # Support old (2.6) format + vertices = vertices.keys + end + vertices.each { |v| add_vertex(v) } + edges.each { |e| add_edge(e) } + var.each do |varname, value| + instance_variable_set("@#{varname}", value) + end + end end diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb index 6b5af8350..4a4f30ae9 100644 --- a/lib/puppet/util/monkey_patches.rb +++ b/lib/puppet/util/monkey_patches.rb @@ -48,3 +48,16 @@ if RUBY_VERSION == '1.8.7' end end +# Workaround for yaml_initialize, which isn't supported before Ruby +# 1.8.3. +if RUBY_VERSION == '1.8.1' || RUBY_VERSION == '1.8.2' + YAML.add_ruby_type( /^object/ ) { |tag, val| + type, obj_class = YAML.read_type_class( tag, Object ) + r = YAML.object_maker( obj_class, val ) + if r.respond_to? :yaml_initialize + r.instance_eval { instance_variables.each { |name| remove_instance_variable name } } + r.yaml_initialize(tag, val) + end + r + } +end -- cgit From 21db472640c8e606565c9693d4737f40a1bf8cce Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Mon, 8 Nov 2010 12:04:26 -0800 Subject: (#5233) Randomize tmp dir paths Standardize how we create tmpdirs by using the puppet function instead of Dir.tmpdir. Paired-with: Paul Berry --- lib/puppet/network/handler/fileserver.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb index 27b913ab9..1531f4f5c 100755 --- a/lib/puppet/network/handler/fileserver.rb +++ b/lib/puppet/network/handler/fileserver.rb @@ -5,6 +5,8 @@ require 'cgi' require 'delegate' require 'sync' +require 'puppet/network/handler' +require 'puppet/network/xmlrpc/server' require 'puppet/file_serving' require 'puppet/file_serving/metadata' -- cgit From ec667fd53f9f611641755d086f09cbc61b1ca203 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Thu, 4 Nov 2010 22:26:28 -0700 Subject: Kludge for #5206 -- port of fix for #3536 to yaml The internal format of parameters was changed between 0.25.x and 2.6.x, making them incompatible when serialized. This was fixed for PSON under ticket #3656 (by modifying the data as it was serialized) in: commit f66095d35bc5f9645eb19bbb8cefa342c0181d2d and commit 2edf7fe968ac3d8af9865f65100940747c1fa894 but nothing was done about the other serialization formats. This commit adds a callback to zaml property serialization and uses it to route data through the fixup method added in the commits above, thus fixing the problem "the same way" as it was fixed for PSON under #3656. It does nothing about marshal, mostly because I have not totaly gone over to the dark side (yet). --- lib/puppet/resource.rb | 12 ++++++++++++ lib/puppet/util/zaml.rb | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index 7dea270e8..4f0d50750 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -80,6 +80,18 @@ class Puppet::Resource end end + def yaml_property_munge(x) + case x + when Hash + x.inject({}) { |h,kv| + k,v = kv + h[k] = self.class.value_to_pson_data(v) + h + } + else self.class.value_to_pson_data(x) + end + end + def to_pson(*args) to_pson_data_hash.to_pson(*args) end diff --git a/lib/puppet/util/zaml.rb b/lib/puppet/util/zaml.rb index 64c58f9a3..9fda5ae3b 100644 --- a/lib/puppet/util/zaml.rb +++ b/lib/puppet/util/zaml.rb @@ -120,6 +120,9 @@ class Object def to_yaml_properties instance_variables.sort # Default YAML behavior end + def yaml_property_munge(x) + x + end def zamlized_class_name(root) cls = self.class "!ruby/#{root.name.downcase}#{cls == root ? '' : ":#{cls.respond_to?(:name) ? cls.name : cls}"}" @@ -136,7 +139,7 @@ class Object z.nl v[1..-1].to_zaml(z) # Remove leading '@' z.emit(': ') - instance_variable_get(v).to_zaml(z) + yaml_property_munge(instance_variable_get(v)).to_zaml(z) } end } -- cgit From 4fa24bb4be7fd73af2a25884185f91b42f73d785 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 30 Oct 2010 15:29:19 +0200 Subject: Fix #5127 - error when accessing array elements Accesing an array with an integer index (ie $array[1]) is producing a ruby error: can't convert String into Integer This is because the array index is not properly converted to an number before the array element lookup is performed. Signed-off-by: Brice Figureau --- lib/puppet/parser/ast/leaf.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb index 090d75c4e..fcdd219d7 100644 --- a/lib/puppet/parser/ast/leaf.rb +++ b/lib/puppet/parser/ast/leaf.rb @@ -148,12 +148,20 @@ class Puppet::Parser::AST key.respond_to?(:evaluate) ? key.safeevaluate(scope) : key end + def array_index_or_key(object, key) + if object.is_a?(Array) + raise Puppet::ParserError, "#{key} is not an integer, but is used as an index of an array" unless key = Puppet::Parser::Scope.number?(key) + end + key + end + def evaluate(scope) object = evaluate_container(scope) + accesskey = evaluate_key(scope) raise Puppet::ParseError, "#{variable} is not an hash or array when accessing it with #{accesskey}" unless object.is_a?(Hash) or object.is_a?(Array) - object[evaluate_key(scope)] + object[array_index_or_key(object, accesskey)] end # Assign value to this hashkey or array index @@ -166,7 +174,7 @@ class Puppet::Parser::AST end # assign to hash or array - object[accesskey] = value + object[array_index_or_key(object, accesskey)] = value end def to_s -- cgit From 956296a74c701fee79d8eed898ce64da02c983de Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 16 Oct 2010 17:47:50 +0200 Subject: Fix #4911 - Do not generate doc for standard RDoc parser generated object RDoc has some standard parsers for .c,.cc or fortran files (don't ask why). Unfortunately our html generator doesn't support the data structures generated by those parsers and we were bombing on unknown methods. This patch makes sure we generate html only for our own top level objects. Signed-off-by: Brice Figureau --- lib/puppet/util/rdoc/generators/puppet_generator.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/util/rdoc/generators/puppet_generator.rb b/lib/puppet/util/rdoc/generators/puppet_generator.rb index 9caeacd5e..e6bbb2e1e 100644 --- a/lib/puppet/util/rdoc/generators/puppet_generator.rb +++ b/lib/puppet/util/rdoc/generators/puppet_generator.rb @@ -88,6 +88,12 @@ module Generators @modules = {} @allclasses = {} + # remove unknown toplevels + # it can happen that RDoc triggers a different parser for some files (ie .c, .cc or .h) + # in this case RDoc generates a RDoc::TopLevel which we do not support in this generator + # So let's make sure we don't generate html for those. + @toplevels = @toplevels.select { |tl| tl.is_a? RDoc::PuppetTopLevel } + # build the modules, classes and per modules classes and define list @toplevels.each do |toplevel| next unless toplevel.document_self -- cgit From 6e6712b543949bc5bb98e63cfdf4112c79adc28c Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 21 Sep 2010 14:41:17 -0700 Subject: [#4813] Remove dead code from puppet/rails/host.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit def self.clean – became orphaned in commit 28cee40689440388994a4768bd301ae32c8ecc05 def self.store – became orphaned in commit 863c50b1273a7fa48d74fb74948938214b45967c def fact – was added as a helper method for unit tests in commit 9f4870637ce57d548d23c0b3330200014327c268. The test file that used this method was removed in commit 93246c0c70796a606fc8c05b51e1feb09c94e377 def update_connect_time – Not sure when this was ever used. I also ran a client master storeconfigs run a few times and didn’t see any problems, so I’m pretty sure deleting these methods is safe. --- lib/puppet/rails/host.rb | 72 ------------------------------------------------ 1 file changed, 72 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/rails/host.rb b/lib/puppet/rails/host.rb index 986cebd0a..b9dea2a3d 100644 --- a/lib/puppet/rails/host.rb +++ b/lib/puppet/rails/host.rb @@ -16,16 +16,6 @@ class Puppet::Rails::Host < ActiveRecord::Base belongs_to :source_file has_many :resources, :dependent => :destroy, :class_name => "Puppet::Rails::Resource" - # If the host already exists, get rid of its objects - def self.clean(host) - if obj = self.find_by_name(host) - obj.rails_objects.clear - return obj - else - return nil - end - end - def self.from_puppet(node) host = find_by_name(node.name) || new(:name => node.name) @@ -38,63 +28,6 @@ class Puppet::Rails::Host < ActiveRecord::Base host end - # Store our host in the database. - def self.store(node, resources) - args = {} - - host = nil - railsmark "Stored node" do - transaction do - #unless host = find_by_name(name) - - debug_benchmark("Searched for host")do - unless host = find_by_name(node.name) - host = new(:name => node.name) - end - end - if ip = node.parameters["ipaddress"] - host.ip = ip - end - - if env = node.environment - host.environment = env - end - - # Store the facts into the database. - host.merge_facts(node.parameters) - - debug_benchmark("Handled resources") { - host.merge_resources(resources) - } - - host.last_compile = Time.now - - debug_benchmark("Saved host") { - host.save - } - end - - end - - # This only runs if time debugging is enabled. - write_benchmarks - - host - end - - # Return the value of a fact. - def fact(name) - - if fv = self.fact_values.find( - :all, :include => :fact_name, - - :conditions => "fact_names.name = '#{name}'") - return fv - else - return nil - end - end - # returns a hash of fact_names.name => [ fact_values ] for this host. # Note that 'fact_values' is actually a list of the value instances, not # just actual values. @@ -305,11 +238,6 @@ class Puppet::Rails::Host < ActiveRecord::Base end end - def update_connect_time - self.last_connect = Time.now - save - end - def to_puppet node = Puppet::Node.new(self.name) {"ip" => "ipaddress", "environment" => "environment"}.each do |myparam, itsparam| -- cgit From 06c8748cbfed67b2440e11577a52f60c43277217 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 16 Oct 2010 19:10:43 +0200 Subject: Fix #3808 - puppetdoc should use --force-update only if RDoc supports it This should allow to run puppetdoc on ruby 1.8.5. Signed-off-by: Brice Figureau --- lib/puppet/util/rdoc.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util/rdoc.rb b/lib/puppet/util/rdoc.rb index 085d8ec93..bdac579d6 100644 --- a/lib/puppet/util/rdoc.rb +++ b/lib/puppet/util/rdoc.rb @@ -10,24 +10,25 @@ module Puppet::Util::RDoc # then rdoc require 'rdoc/rdoc' + require 'rdoc/options' # load our parser require 'puppet/util/rdoc/parser' r = RDoc::RDoc.new - RDoc::RDoc::GENERATORS["puppet"] = RDoc::RDoc::Generator.new( + RDoc::RDoc::GENERATORS["puppet"] = RDoc::RDoc::Generator.new( "puppet/util/rdoc/generators/puppet_generator.rb", - "PuppetGenerator".intern, + "PuppetGenerator".intern, + "puppet") - "puppet") # specify our own format & where to output options = [ "--fmt", "puppet", "--quiet", - "--force-update", "--exclude", "/modules/[^/]*/files/.*\.pp$", "--op", outputdir ] + options << "--force-update" if Options::OptionList.options.any? { |o| o[0] == "--force-update" } options += [ "--charset", charset] if charset options += files -- cgit From 4cbceab68f3d84b322d9b78ddb95c34615906bb9 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 4 Oct 2010 15:23:02 -0700 Subject: (#4573) FreeBSD service provider now supports versions <7 and >8 Running "/etc/rc.d/SERVICE rcvar" outputs different formats for different versions of FreeBSD. This patch adds support for those formats, as well as tests. Based on patches from: o Joost van Beurden o Russell Jackson Paired-With: Matt Robinson --- lib/puppet/provider/service/freebsd.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/service/freebsd.rb b/lib/puppet/provider/service/freebsd.rb index c75c3c9ab..f8c7134f0 100644 --- a/lib/puppet/provider/service/freebsd.rb +++ b/lib/puppet/provider/service/freebsd.rb @@ -18,6 +18,9 @@ Puppet::Type.type(:service).provide :freebsd, :parent => :init do def rcvar rcvar = execute([self.initscript, :rcvar], :failonfail => true, :squelch => false) rcvar = rcvar.split("\n") + rcvar.delete_if {|str| str =~ /^#\s*$/} + rcvar[1] = rcvar[1].gsub(/^\$/, '') + rcvar end # Extract service name @@ -44,7 +47,7 @@ Puppet::Type.type(:service).provide :freebsd, :parent => :init do def rcvar_value value = self.rcvar[1] self.error("No rcvar value found in rcvar") if value.nil? - value = value.gsub!(/(.*)_enable=\"?(.*)\"?/, '\2') + value = value.gsub!(/(.*)_enable="?(\w+)"?/, '\2') self.error("rcvar value is empty") if value.nil? self.debug("rcvar value is #{value}") value -- cgit From 00eedac5917fdc4ca5cee5c831e7f2e105a668a4 Mon Sep 17 00:00:00 2001 From: Nigel Kersten Date: Thu, 30 Sep 2010 16:44:48 -0700 Subject: capture stderr from exec resources --- lib/puppet/util/suidmanager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb index 4d2c32217..6633de002 100644 --- a/lib/puppet/util/suidmanager.rb +++ b/lib/puppet/util/suidmanager.rb @@ -88,7 +88,7 @@ module Puppet::Util::SUIDManager module_function :initgroups def run_and_capture(command, new_uid=nil, new_gid=nil) - output = Puppet::Util.execute(command, :failonfail => false, :uid => new_uid, :gid => new_gid) + output = Puppet::Util.execute(command, :failonfail => false, :combine => true, :uid => new_uid, :gid => new_gid) [output, $CHILD_STATUS.dup] end module_function :run_and_capture -- cgit From 9ba0c8a22c6f9ca856851ef6c2d38242754a7a00 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 16 Oct 2010 15:10:28 +0200 Subject: Fix #4923 - close process race when truncating existing file Using File.open(file, "w") calls open(2) with O_CREAT|O_TRUNC which means when the file exists it is immediately truncated. But the file is not locked yet, so another process can either write or read to the file, leading to file corruption. The fix is to truncate only when the file is exclusively locked. This can be done on some operating system with O_EXLOCK open(2) flag. I chose the more portable option of: * open * flock * truncate * write * close It might also be good to flush and fsync the file after writing it, otherwise in case of crash an incomplete file can stay on disk. Signed-off-by: Brice Figureau --- lib/puppet/util/file_locking.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util/file_locking.rb b/lib/puppet/util/file_locking.rb index 8b194ed83..bd0181733 100644 --- a/lib/puppet/util/file_locking.rb +++ b/lib/puppet/util/file_locking.rb @@ -34,8 +34,11 @@ module Puppet::Util::FileLocking end Puppet::Util.sync(file).synchronize(Sync::EX) do - File.open(file, "w", mode) do |rf| + File.open(file, File::Constants::CREAT | File::Constants::WRONLY, mode) do |rf| rf.lock_exclusive do |lrf| + # poor's man open(2) O_EXLOCK|O_TRUNC + lrf.seek(0, IO::SEEK_SET) + lrf.truncate(0) yield lrf end end -- cgit From 235d64163c9565b9e07be0873248a7da07033bff Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Wed, 22 Sep 2010 11:38:28 -0700 Subject: Refactor for CLA This commit removes code contributed by Ryan McBride, an author we have been unable to contact to sign a Contributor License Agreement. It also removes code writen by Matt Robinson (a Puppet Labs employee) which only made sense in the context of the removed code. The code in question comes from these commits: 6ac36eb4 Matt Robinson 55a9009c Ryan McBride --- lib/puppet/provider/package/openbsd.rb | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 22df14d62..0891844bc 100755 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -2,7 +2,6 @@ require 'puppet/provider/package' # Packaging on OpenBSD. Doesn't work anywhere else that I know of. Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Package do - include Puppet::Util::Execution desc "OpenBSD's form of `pkg_add` support." commands :pkginfo => "pkg_info", :pkgadd => "pkg_add", :pkgdelete => "pkg_delete" @@ -61,18 +60,7 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa "You must specify a package source for BSD packages" end - old_ensure = @resource[:ensure] - - if @resource[:source] =~ /\/$/ - withenv :PKG_PATH => @resource[:source] do - @resource[:ensure] = old_ensure if (@resource[:ensure] = get_version) == nil - full_name = [ @resource[:name], @resource[:ensure], @resource[:flavor] ] - pkgadd full_name.join('-').chomp('-') - end - else - pkgadd @resource[:source] - end - + pkgadd @resource[:source] end def get_version -- cgit From 4a3d5d7c11bea5efba6f8fa8074b52c7161fd1d3 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Wed, 22 Sep 2010 16:21:33 -0700 Subject: Reimplementation of functionality removed by prior commit This commit implements the base path-to-source functionality and adds an (adapted) version of Matt's code on top of it. --- lib/puppet/provider/package/openbsd.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 0891844bc..bb07d894a 100755 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -60,7 +60,15 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa "You must specify a package source for BSD packages" end - pkgadd @resource[:source] + if @resource[:source][-1,1] == ::File::PATH_SEPARATOR + e_vars = { :PKG_PATH => @resource[:source] } + full_name = [ @resource[:name], get_version || @resource[:ensure], @resource[:flavor] ].join('-').chomp('-') + else + e_vars = {} + full_name = @resource[:source] + end + + Puppet::Util::Execution::withenv(e_vars) { pkgadd full_name } end def get_version -- cgit From ba4d22bce3fbb7af3bef50088623605350a9891e Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Mon, 1 Nov 2010 15:58:09 -0700 Subject: Maint. Removing code for which no CLA has been signed Multiple attemps were made to contact the author of this code in order to obtain a Contributor Licence Agreement, but we were unable to do so. --- lib/puppet/defaults.rb | 3 --- lib/puppet/rails.rb | 6 ------ 2 files changed, 9 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 972e9e66c..72b1af188 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -665,9 +665,6 @@ module Puppet used when networked databases are used."], :dbsocket => [ "", "The database socket location. Only used when networked databases are used. Will be ignored if the value is an empty string."], - :dbconnections => [ 0, "The number of database connections. Only used when - networked databases are used. Will be ignored if the value is an empty - string or is less than 1."], :railslog => {:default => "$logdir/rails.log", :mode => 0600, :owner => "service", diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb index c2d492fdd..44e7a8343 100644 --- a/lib/puppet/rails.rb +++ b/lib/puppet/rails.rb @@ -57,16 +57,10 @@ module Puppet::Rails socket = Puppet[:dbsocket] args[:socket] = socket unless socket.to_s.empty? - - connections = Puppet[:dbconnections].to_i - args[:pool] = connections if connections > 0 when "oracle_enhanced": args[:database] = Puppet[:dbname] unless Puppet[:dbname].to_s.empty? args[:username] = Puppet[:dbuser] unless Puppet[:dbuser].to_s.empty? args[:password] = Puppet[:dbpassword] unless Puppet[:dbpassword].to_s.empty? - - connections = Puppet[:dbconnections].to_i - args[:pool] = connections if connections > 0 else raise ArgumentError, "Invalid db adapter #{adapter}" end -- cgit From 5f7d0fbb3699cba28d10adac62c69aedfce2df38 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Tue, 2 Nov 2010 11:10:33 -0700 Subject: Fix for #2568 -- Add a dbconnections option to set AR pool size The dbconnection option, if set to a positive integer, will be passed to active record as the connection pool size (pool). --- lib/puppet/defaults.rb | 2 ++ lib/puppet/rails.rb | 2 ++ 2 files changed, 4 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 72b1af188..b8437fe29 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -663,6 +663,8 @@ module Puppet used when networked databases are used."], :dbpassword => [ "puppet", "The database password for caching. Only used when networked databases are used."], + :dbconnections => [ '', "The number of database connections for networked + databases. Will be ignored unless the value is a positive integer."], :dbsocket => [ "", "The database socket location. Only used when networked databases are used. Will be ignored if the value is an empty string."], :railslog => {:default => "$logdir/rails.log", diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb index 44e7a8343..74805bb6f 100644 --- a/lib/puppet/rails.rb +++ b/lib/puppet/rails.rb @@ -52,6 +52,7 @@ module Puppet::Rails args[:port] = Puppet[:dbport] unless Puppet[:dbport].to_s.empty? args[:username] = Puppet[:dbuser] unless Puppet[:dbuser].to_s.empty? args[:password] = Puppet[:dbpassword] unless Puppet[:dbpassword].to_s.empty? + args[:pool] = Puppet[:dbconnections].to_i unless Puppet[:dbconnections].to_i <= 0 args[:database] = Puppet[:dbname] args[:reconnect]= true @@ -61,6 +62,7 @@ module Puppet::Rails args[:database] = Puppet[:dbname] unless Puppet[:dbname].to_s.empty? args[:username] = Puppet[:dbuser] unless Puppet[:dbuser].to_s.empty? args[:password] = Puppet[:dbpassword] unless Puppet[:dbpassword].to_s.empty? + args[:pool] = Puppet[:dbconnections].to_i unless Puppet[:dbconnections].to_i <= 0 else raise ArgumentError, "Invalid db adapter #{adapter}" end -- cgit From 9604f1c4cd5a368da08c6f3219b44908a9b9921c Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Thu, 11 Nov 2010 15:51:21 +0100 Subject: Fix #5252 - line number mis-attribution during parsing It is a resurgence of #2366 that appeared because of the commit 8971d8. Before this commit, for associating documentation comments, we were preferring line numbers coming from the parser currently reducing rule, instead of the current lexer line number (which can be in advance of several tokens due to the nature of LALR parsers). We now merge the ast line number before fetching the comment from the lexer. Signed-off-by: Brice Figureau --- lib/puppet/parser/parser_support.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index c90c1978f..7bbebb124 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -46,12 +46,12 @@ class Puppet::Parser::Parser # Create an AST object, and automatically add the file and line information if # available. def ast(klass, hash = {}) - klass.new ast_context(klass.use_docs).merge(hash) + klass.new ast_context(klass.use_docs, hash[:line]).merge(hash) end - def ast_context(include_docs = false) + def ast_context(include_docs = false, ast_line = nil) result = { - :line => lexer.line, + :line => ast_line || lexer.line, :file => lexer.file } result[:doc] = lexer.getcomment(result[:line]) if include_docs -- cgit From f57425da6aeefd4ff019068c5933add0d2a02f87 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 16 Oct 2010 20:04:57 +0200 Subject: Fix #4921 - race condition in Parser Functions creation The autoloading is not thread safe, which means two threads could both autoload the same function at the same time. Signed-off-by: Brice Figureau --- lib/puppet/parser/functions.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb index b0deac5bc..5807c0bbe 100644 --- a/lib/puppet/parser/functions.rb +++ b/lib/puppet/parser/functions.rb @@ -73,8 +73,10 @@ module Puppet::Parser::Functions def self.function(name) name = symbolize(name) - unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name) - autoloader.load(name,Environment.current || Environment.root) + @functions.synchronize do + unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name) + autoloader.load(name,Environment.current || Environment.root) + end end ( functions(Environment.root)[name] || functions[name] || {:name => false} )[:name] -- cgit From ee61b4ecec7d5a993eac6a356b4bc0dcc6ceaf94 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Mon, 18 Oct 2010 15:55:41 -0700 Subject: Fix for #4955 -- Race condition & memory leak in Puppet::Util The Puppet::Util.sync method was not thread safe and also leaked memory. I'm not certain, but I believe the first is ironic and the second is merely a bug. This patch addresses the problem by 1) refactoring so the sync objects are never returned (and thus no one can cache a reference to one) 2) adding reference counting 3) deleting them when they are no longer needed 4) doing the thread safty dance. It wasn't the first (or even second) solution considered, but it's the one that I was able to make work in a way that I'm convinced is correct. Its main advantage is that it puts all the tricky bits in one place. --- lib/puppet/daemon.rb | 4 ++-- lib/puppet/network/server.rb | 4 ++-- lib/puppet/util.rb | 25 ++++++++++++++++--------- lib/puppet/util/file_locking.rb | 4 ++-- 4 files changed, 22 insertions(+), 15 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb index ad0edd3b9..c76d63a54 100755 --- a/lib/puppet/daemon.rb +++ b/lib/puppet/daemon.rb @@ -43,7 +43,7 @@ class Puppet::Daemon # Create a pidfile for our daemon, so we can be stopped and others # don't try to start. def create_pidfile - Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do + Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do raise "Could not create PID file: #{pidfile}" unless Puppet::Util::Pidlock.new(pidfile).lock end end @@ -73,7 +73,7 @@ class Puppet::Daemon # Remove the pid file for our daemon. def remove_pidfile - Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do + Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do locker = Puppet::Util::Pidlock.new(pidfile) locker.unlock or Puppet.err "Could not remove PID file #{pidfile}" if locker.locked? end diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb index d424b9c4a..e4de07dea 100644 --- a/lib/puppet/network/server.rb +++ b/lib/puppet/network/server.rb @@ -32,14 +32,14 @@ class Puppet::Network::Server # Create a pidfile for our daemon, so we can be stopped and others # don't try to start. def create_pidfile - Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do + Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do raise "Could not create PID file: #{pidfile}" unless Puppet::Util::Pidlock.new(pidfile).lock end end # Remove the pid file for our daemon. def remove_pidfile - Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do + Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do locker = Puppet::Util::Pidlock.new(pidfile) locker.unlock or Puppet.err "Could not remove PID file #{pidfile}" if locker.locked? end diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index f2eaf0d06..1a5acaf22 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -3,6 +3,7 @@ require 'puppet/util/monkey_patches' require 'sync' require 'puppet/external/lock' +require 'monitor' module Puppet # A command failed to execute. @@ -17,8 +18,7 @@ module Util require 'puppet/util/posix' extend Puppet::Util::POSIX - # Create a hash to store the different sync objects. - @@syncresources = {} + @@sync_objects = {}.extend MonitorMixin def self.activerecord_version if (defined?(::ActiveRecord) and defined?(::ActiveRecord::VERSION) and defined?(::ActiveRecord::VERSION::MAJOR) and defined?(::ActiveRecord::VERSION::MINOR)) @@ -28,10 +28,19 @@ module Util end end - # Return the sync object associated with a given resource. - def self.sync(resource) - @@syncresources[resource] ||= Sync.new - @@syncresources[resource] + + def self.synchronize_on(x,type) + sync_object,users = 0,1 + begin + @@sync_objects.synchronize { + (@@sync_objects[x] ||= [Sync.new,0])[users] += 1 + } + @@sync_objects[x][sync_object].synchronize(type) { yield } + ensure + @@sync_objects.synchronize { + @@sync_objects.delete(x) unless (@@sync_objects[x][users] -= 1) > 0 + } + end end # Change the process to a different user @@ -359,9 +368,7 @@ module Util # Create an exclusive lock. def threadlock(resource, type = Sync::EX) - Puppet::Util.sync(resource).synchronize(type) do - yield - end + Puppet::Util.synchronize_on(resource,type) { yield } end # Because some modules provide their own version of this method. diff --git a/lib/puppet/util/file_locking.rb b/lib/puppet/util/file_locking.rb index bd0181733..18744cab7 100644 --- a/lib/puppet/util/file_locking.rb +++ b/lib/puppet/util/file_locking.rb @@ -6,7 +6,7 @@ module Puppet::Util::FileLocking # Create a shared lock for reading def readlock(file) raise ArgumentError, "#{file} is not a file" unless !File.exists?(file) or File.file?(file) - Puppet::Util.sync(file).synchronize(Sync::SH) do + Puppet::Util.synchronize_on(file,Sync::SH) do File.open(file) { |f| f.lock_shared { |lf| yield lf } } @@ -33,7 +33,7 @@ module Puppet::Util::FileLocking end end - Puppet::Util.sync(file).synchronize(Sync::EX) do + Puppet::Util.synchronize_on(file,Sync::EX) do File.open(file, File::Constants::CREAT | File::Constants::WRONLY, mode) do |rf| rf.lock_exclusive do |lrf| # poor's man open(2) O_EXLOCK|O_TRUNC -- cgit From ea435a43dc97487d054271a9efb208f361408339 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 16 Oct 2010 16:58:04 +0200 Subject: Fix #5020 - Prefer finding node name from REST uri over certname This is a behavior change. Before this patch, we always used the currently connected node's certname to compile the catalog, despite the value of the catalog URI REST request. With this patch we now use the URI as the compiled node name. This is safe because the default auth.conf (and default inserted rules when no auth.conf is present) only allow the given connected node to compile its own catalog. But this also allows for greater flexibility with auth.conf. For instance it can be used by a monitoring system to check multiple nodes catalogs with only one certificate: path ~ ^/catalog/([^/]+)$ method find allow $1 allow monitoring-station.domain.com Signed-off-by: Brice Figureau --- lib/puppet/indirector/catalog/compiler.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb index c50022fff..6375e801f 100644 --- a/lib/puppet/indirector/catalog/compiler.rb +++ b/lib/puppet/indirector/catalog/compiler.rb @@ -107,10 +107,14 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code return node end - # If the request is authenticated, then the 'node' info will - # be available; if not, then we use the passed-in key. We rely - # on our authorization system to determine whether this is allowed. - name = request.node || request.key + # We rely on our authorization system to determine whether the connected + # node is allowed to compile the catalog's node referenced by key. + # By default the REST authorization system makes sure only the connected node + # can compile his catalog. + # This allows for instance monitoring systems or puppet-load to check several + # node's catalog with only one certificate and a modification to auth.conf + # If no key is provided we can only compile the currently connected node. + name = request.key || request.node if node = find_node(name) return node end -- cgit From b15231df5842df2ea83b779b22e6756e51bc39d0 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Thu, 4 Nov 2010 13:53:23 -0700 Subject: Fix for #4299 -- Don't require which We already had an internal implementation of which hiding under an assumed name (Puppet::Util.binary); this commit calls it out of hiding and uses it consisantly. --- lib/puppet/defaults.rb | 2 +- lib/puppet/provider.rb | 4 ++-- lib/puppet/provider/confine/exists.rb | 5 +---- lib/puppet/type/exec.rb | 8 +------- lib/puppet/util.rb | 13 ++++--------- lib/puppet/util/command_line.rb | 2 +- lib/puppet/util/reference.rb | 9 +-------- 7 files changed, 11 insertions(+), 32 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index b8437fe29..93b01c779 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -637,7 +637,7 @@ module Puppet setdefaults( :tagmail, :tagmap => ["$confdir/tagmail.conf", "The mapping between reporting tags and email addresses."], - :sendmail => [%x{which sendmail 2>/dev/null}.chomp, "Where to find the sendmail binary with which to send email."], + :sendmail => [which('sendmail') || '', "Where to find the sendmail binary with which to send email."], :reportfrom => ["report@" + [Facter["hostname"].value, Facter["domain"].value].join("."), "The 'from' email address for the reports."], :smtpserver => ["none", "The server through which to send email reports."] diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb index af792b623..4456feb4e 100644 --- a/lib/puppet/provider.rb +++ b/lib/puppet/provider.rb @@ -12,7 +12,7 @@ class Puppet::Provider Puppet::Util.logmethods(self, true) class << self - # Include the util module so we have access to things like 'binary' + # Include the util module so we have access to things like 'which' include Puppet::Util, Puppet::Util::Docs include Puppet::Util::Logging attr_accessor :name @@ -43,7 +43,7 @@ class Puppet::Provider raise Puppet::DevError, "No command #{name} defined for provider #{self.name}" end - binary(command) + which(command) end # Define commands that are not optional. diff --git a/lib/puppet/provider/confine/exists.rb b/lib/puppet/provider/confine/exists.rb index 085118b2a..09f94dfd9 100644 --- a/lib/puppet/provider/confine/exists.rb +++ b/lib/puppet/provider/confine/exists.rb @@ -6,10 +6,7 @@ class Puppet::Provider::Confine::Exists < Puppet::Provider::Confine end def pass?(value) - if for_binary? - return false unless value = binary(value) - end - value and FileTest.exist?(value) + value && (for_binary? ? which(value) : FileTest.exist?(value)) end def message(value) diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb index dd57ec231..606888c75 100755 --- a/lib/puppet/type/exec.rb +++ b/lib/puppet/type/exec.rb @@ -553,13 +553,7 @@ module Puppet if self[:path] if Puppet.features.posix? and !File.exists?(exe) withenv :PATH => self[:path].join(File::PATH_SEPARATOR) do - path = %x{which #{exe}}.chomp - if path == "" - raise ArgumentError, - "Could not find command '#{exe}'" - else - exe = path - end + exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'") end elsif Puppet.features.microsoft_windows? and !File.exists?(exe) self[:path].each do |path| diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index 1a5acaf22..850d147e2 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -198,7 +198,7 @@ module Util end end - def binary(bin) + def which(bin) if bin =~ /^\// return bin if FileTest.file? bin and FileTest.executable? bin else @@ -209,7 +209,7 @@ module Util end nil end - module_function :binary + module_function :which # Execute the provided command in a pipe, yielding the pipe object. def execpipe(command, failonfail = true) @@ -378,15 +378,10 @@ module Util def memory unless defined?(@pmap) - pmap = %x{which pmap 2>/dev/null}.chomp - if $CHILD_STATUS != 0 or pmap =~ /^no/ - @pmap = nil - else - @pmap = pmap - end + @pmap = which('pmap') end if @pmap - return %x{pmap #{Process.pid}| grep total}.chomp.sub(/^\s*total\s+/, '').sub(/K$/, '').to_i + %x{#{@pmap} #{Process.pid}| grep total}.chomp.sub(/^\s*total\s+/, '').sub(/K$/, '').to_i else 0 end diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index 2a97ee069..3562a3dc0 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -62,7 +62,7 @@ module Puppet external_command = "puppet-#{subcommand_name}" require 'puppet/util' - path_to_subcommand = Puppet::Util.binary( external_command ) + path_to_subcommand = Puppet::Util.which( external_command ) return false unless path_to_subcommand system( path_to_subcommand, *args ) diff --git a/lib/puppet/util/reference.rb b/lib/puppet/util/reference.rb index ab201cde4..95efeb1c1 100644 --- a/lib/puppet/util/reference.rb +++ b/lib/puppet/util/reference.rb @@ -39,14 +39,7 @@ class Puppet::Util::Reference Puppet::Util.secure_open("/tmp/puppetdoc.txt", "w") do |f| f.puts text end - rst2latex = %x{which rst2latex} - if $CHILD_STATUS != 0 or rst2latex =~ /no / - rst2latex = %x{which rst2latex.py} - end - if $CHILD_STATUS != 0 or rst2latex =~ /no / - raise "Could not find rst2latex" - end - rst2latex.chomp! + rst2latex = which('rst2latex') || which('rst2latex.py') || raise("Could not find rst2latex") cmd = %{#{rst2latex} /tmp/puppetdoc.txt > /tmp/puppetdoc.tex} Puppet::Util.secure_open("/tmp/puppetdoc.tex","w") do |f| # If we get here without an error, /tmp/puppetdoc.tex isn't a tricky cracker's symlink -- cgit From 4d31430275016c9abbd4f621e731ff2eeb1718e5 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Fri, 12 Nov 2010 13:39:41 +0100 Subject: Fix #4339 - Save a last run report summary to $statedir/last_run_summary.yaml Once a configuration run is done, puppetd will save on the node a yaml summary report roughly akin to: --- time: notify: 0.001025 last_run: 1289561427 schedule: 0.00071 config_retrieval: 0.039518 filebucket: 0.000126 resources: changed: 1 total: 8 out_of_sync: 1 events: total: 1 success: 1 changes: total: 1 This is almost an hash version of the current --summarize output, with the notable exception that the time section includes the last run unix timestamp. The whole idea is to be able to monitor locally if a puppetd does its job. For instance this could be used in a nagios check or to send an SNMP trap. The last_run information might help detect staleness, and this summary can also be used for performance monitoring (ie time section). The resource section can also show the number of failed resources. Signed-off-by: Brice Figureau --- lib/puppet/configurer.rb | 15 +++++++++++++-- lib/puppet/defaults.rb | 4 ++++ lib/puppet/transaction/report.rb | 39 ++++++++++++++++++++++++++++----------- lib/puppet/util/metric.rb | 8 +++----- 4 files changed, 48 insertions(+), 18 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb index 31d31c2d2..e46e9a6e7 100644 --- a/lib/puppet/configurer.rb +++ b/lib/puppet/configurer.rb @@ -168,19 +168,30 @@ class Puppet::Configurer execute_postrun_command Puppet::Util::Log.close(report) - send_report(report, transaction) end def send_report(report, trans = nil) trans.generate_report if trans puts report.summary if Puppet[:summarize] - report.save if Puppet[:report] + save_last_run_summary(report) + if Puppet[:report] + report.save + end rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not send report: #{detail}" end + def save_last_run_summary(report) + Puppet::Util::FileLocking.writelock(Puppet[:lastrunfile], 0660) do |file| + file.print YAML.dump(report.raw_summary) + end + rescue => detail + puts detail.backtrace if Puppet[:trace] + Puppet.err "Could not save last run local report: #{detail}" + end + private def self.timeout diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 7ae553827..9b80c9262 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -602,6 +602,10 @@ module Puppet :report => [false, "Whether to send reports after every transaction." ], + :lastrunfile => { :default => "$statedir/last_run_summary.yaml", + :mode => 0660, + :desc => "Where puppet agent stores the last run report summary in yaml format." + }, :graph => [false, "Whether to create dot graph files for the different configuration graphs. These dot files can be interpreted by tools like OmniGraffle or dot (which is part of ImageMagick)."], diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb index e6d1e0528..1d3091428 100644 --- a/lib/puppet/transaction/report.rb +++ b/lib/puppet/transaction/report.rb @@ -62,30 +62,49 @@ class Puppet::Transaction::Report host end - # Provide a summary of this report. + # Provide a human readable textual summary of this report. def summary + report = raw_summary + ret = "" + report.keys.sort { |a,b| a.to_s <=> b.to_s }.each do |key| + ret += "#{Puppet::Util::Metric.labelize(key)}:\n" - @metrics.sort { |a,b| a[1].label <=> b[1].label }.each do |name, metric| - ret += "#{metric.label}:\n" - metric.values.sort { |a,b| + report[key].keys.sort { |a,b| # sort by label - if a[0] == :total + if a == :total 1 - elsif b[0] == :total + elsif b == :total -1 else - a[1] <=> b[1] + report[key][a].to_s <=> report[key][b].to_s end - }.each do |name, label, value| + }.each do |label| + value = report[key][label] next if value == 0 value = "%0.2f" % value if value.is_a?(Float) - ret += " %15s %s\n" % [label + ":", value] + ret += " %15s %s\n" % [Puppet::Util::Metric.labelize(label) + ":", value] end end ret end + # Provide a raw hash summary of this report. + def raw_summary + report = {} + + @metrics.each do |name, metric| + key = metric.name.to_s + report[key] = {} + metric.values.each do |name, label, value| + report[key][name.to_s] = value + end + report[key]["total"] = 0 unless key == "time" or report[key].include?("total") + end + (report["time"] ||= {})["last_run"] = Time.now.tv_sec + report + end + # Based on the contents of this report's metrics, compute a single number # that represents the report. The resulting number is a bitmask where # individual bits represent the presence of different metrics. @@ -103,7 +122,6 @@ class Puppet::Transaction::Report resource_statuses.each do |name, status| metrics[:total] += status.change_count if status.change_count end - add_metric(:changes, metrics) end @@ -124,7 +142,6 @@ class Puppet::Transaction::Report metrics[:total] = resource_statuses.length resource_statuses.each do |name, status| - Puppet::Resource::Status::STATES.each do |state| metrics[state] += 1 if status.send(state) end diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb index 90a244836..d61fb3df6 100644 --- a/lib/puppet/util/metric.rb +++ b/lib/puppet/util/metric.rb @@ -122,7 +122,7 @@ class Puppet::Util::Metric def initialize(name,label = nil) @name = name.to_s - @label = label || labelize(name) + @label = label || self.class.labelize(name) @values = [] end @@ -132,7 +132,7 @@ class Puppet::Util::Metric end def newvalue(name,value,label = nil) - label ||= labelize(name) + label ||= self.class.labelize(name) @values.push [name,label,value] end @@ -173,10 +173,8 @@ class Puppet::Util::Metric @values.sort { |a, b| a[1] <=> b[1] } end - private - # Convert a name into a label. - def labelize(name) + def self.labelize(name) name.to_s.capitalize.gsub("_", " ") end end -- cgit From 8ab1aba853231a5e541346955dcd502a67992eb6 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Fri, 12 Nov 2010 13:41:00 +0100 Subject: Fix #4339 - Allow puppet apply to save last run summary Puppet apply inconditionally saves its last run summary like puppet agent. Signed-off-by: Brice Figureau --- lib/puppet/application/apply.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index 59a95d35a..ed1331d63 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -139,6 +139,7 @@ class Puppet::Application::Apply < Puppet::Application configurer.send_report(report, transaction) else transaction.generate_report + configurer.save_last_run_summary(transaction.report) end exit( Puppet[:noop] ? 0 : options[:detailed_exitcodes] ? transaction.report.exit_status : 0 ) -- cgit From ccc944f21a259f0216b0bfd4873c98d89127a753 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Sat, 13 Nov 2010 11:41:18 +0100 Subject: Fix #4339 - Locally save the last report to $lastrunreport Using the cache terminus system, when --report is on, we are now caching the last report as a yaml file in the $lastrunreport file (which by default is $statedir/last_run_report.yaml). Signed-off-by: Brice Figureau --- lib/puppet/application/agent.rb | 2 ++ lib/puppet/application/apply.rb | 3 +++ lib/puppet/defaults.rb | 4 ++++ lib/puppet/indirector/report/yaml.rb | 11 +++++++++++ 4 files changed, 20 insertions(+) create mode 100644 lib/puppet/indirector/report/yaml.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb index 2b75505fd..c5ad72068 100644 --- a/lib/puppet/application/agent.rb +++ b/lib/puppet/application/agent.rb @@ -229,6 +229,8 @@ class Puppet::Application::Agent < Puppet::Application Puppet::SSL::Host.ca_location = options[:fingerprint] ? :none : :remote Puppet::Transaction::Report.terminus_class = :rest + # we want the last report to be persisted locally + Puppet::Transaction::Report.cache_class = :yaml # Override the default; puppetd needs this, usually. # You can still override this on the command-line with, e.g., :compiler. diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index ed1331d63..97de5e1ff 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -165,6 +165,9 @@ class Puppet::Application::Apply < Puppet::Application exit(1) end + # we want the last report to be persisted locally + Puppet::Transaction::Report.cache_class = :yaml + if options[:debug] Puppet::Util::Log.level = :debug elsif options[:verbose] diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 9b80c9262..f4ae88602 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -606,6 +606,10 @@ module Puppet :mode => 0660, :desc => "Where puppet agent stores the last run report summary in yaml format." }, + :lastrunreport => { :default => "$statedir/last_run_report.yaml", + :mode => 0660, + :desc => "Where puppet agent stores the last run report in yaml format." + }, :graph => [false, "Whether to create dot graph files for the different configuration graphs. These dot files can be interpreted by tools like OmniGraffle or dot (which is part of ImageMagick)."], diff --git a/lib/puppet/indirector/report/yaml.rb b/lib/puppet/indirector/report/yaml.rb new file mode 100644 index 000000000..bf7bf4fe5 --- /dev/null +++ b/lib/puppet/indirector/report/yaml.rb @@ -0,0 +1,11 @@ +require 'puppet/transaction/report' +require 'puppet/indirector/yaml' + +class Puppet::Transaction::Report::Yaml < Puppet::Indirector::Yaml + desc "Store last report as a flat file, serialized using YAML." + + # Force report to be saved there + def path(name,ext='.yaml') + Puppet[:lastrunreport] + end +end -- cgit From b753d836c5ea18333a1199b20b5c495f562f2af4 Mon Sep 17 00:00:00 2001 From: James Turnbull Date: Sun, 14 Nov 2010 09:16:59 +1100 Subject: Fixed #5288 - Changed report default to true --- lib/puppet/defaults.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 7ae553827..50c5d8c09 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -116,7 +116,7 @@ module Puppet :catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance, you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."], :facts_terminus => { - :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter', + :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter', :desc => "The node facts terminus.", :hook => proc do |value| require 'puppet/node/facts' @@ -599,7 +599,7 @@ module Puppet :inventory_port => ["$masterport", "The port to communicate with the inventory_server." ], - :report => [false, + :report => [true, "Whether to send reports after every transaction." ], :graph => [false, "Whether to create dot graph files for the different -- cgit From f2fd0d1ec854542ee0b1284bccaf698f9ad69b81 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Tue, 16 Nov 2010 10:11:55 -0800 Subject: Fix for #5273 -- user resource constantly resetting password age The query methods for the newly added password age properties didn't have the same name as the properties, and thus the default retrieve method wan't finding them and never got the current value from the provider. They were therefore always seen as :absent and puppet always thought they needed to be set. --- lib/puppet/provider/user/user_role_add.rb | 4 ++-- lib/puppet/provider/user/useradd.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb index caca1ef88..2377f9e65 100644 --- a/lib/puppet/provider/user/user_role_add.rb +++ b/lib/puppet/provider/user/user_role_add.rb @@ -156,11 +156,11 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source => shadow_entry[1] if shadow_entry end - def min_age + def password_min_age shadow_entry ? shadow_entry[3] : :absent end - def max_age + def password_max_age shadow_entry ? shadow_entry[4] : :absent end diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb index 5a163f35a..ba406cc63 100644 --- a/lib/puppet/provider/user/useradd.rb +++ b/lib/puppet/provider/user/useradd.rb @@ -78,7 +78,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ end end - def min_age + def password_min_age if Puppet.features.libshadow? if ent = Shadow::Passwd.getspnam(@resource.name) return ent.sp_min @@ -87,7 +87,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ :absent end - def max_age + def password_max_age if Puppet.features.libshadow? if ent = Shadow::Passwd.getspnam(@resource.name) return ent.sp_max -- cgit From 722608b3592caf31f9fbe096e7e85c33215d33fd Mon Sep 17 00:00:00 2001 From: James Turnbull Date: Sun, 14 Nov 2010 09:35:37 +1100 Subject: Fixed #5287 - Schedule documentation is incorrect --- lib/puppet/type/schedule.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/type/schedule.rb b/lib/puppet/type/schedule.rb index ff3fba8eb..82f17e533 100755 --- a/lib/puppet/type/schedule.rb +++ b/lib/puppet/type/schedule.rb @@ -16,7 +16,7 @@ module Puppet Thus, it behooves you to use wider scheduling (e.g., over a couple of hours) combined with periods and repetitions. For instance, if you wanted to restrict certain resources to only running once, between - the hours of two and 4 AM, then you would use this schedule:: + the hours of two and 4 AM, then you would use this schedule: schedule { maint: range => \"2 - 4\", @@ -33,7 +33,7 @@ module Puppet Puppet automatically creates a schedule for each valid period with the same name as that period (e.g., hourly and daily). Additionally, a schedule named *puppet* is created and used as the default, - with the following attributes:: + with the following attributes: schedule { puppet: period => hourly, @@ -45,11 +45,11 @@ module Puppet newparam(:name) do desc "The name of the schedule. This name is used to retrieve the - schedule when assigning it to an object:: + schedule when assigning it to an object: schedule { daily: period => daily, - range => [2, 4] + range => \"2 - 4\", } exec { \"/usr/bin/apt-get update\": @@ -65,7 +65,7 @@ module Puppet is always a range within a 24 hour period, and hours must be specified in numbers between 0 and 23, inclusive. Minutes and seconds can be provided, using the normal colon as a separator. - For instance:: + For instance: schedule { maintenance: range => \"1:30 - 4:30\" -- cgit From 1ce00dccb840abd9e11432d00c73bdd1de104751 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Mon, 15 Nov 2010 18:49:53 -0800 Subject: Step towards [5298] -- cleanup indentation, etc. in AST::Collection My code smell routines bobbled this one, so I'm fixing it manually. --- lib/puppet/parser/ast/collection.rb | 84 +++++++++++++++---------------------- 1 file changed, 33 insertions(+), 51 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb index 09d5b4eb3..90a914337 100644 --- a/lib/puppet/parser/ast/collection.rb +++ b/lib/puppet/parser/ast/collection.rb @@ -5,61 +5,43 @@ require 'puppet/parser/collector' # An object that collects stored objects from the central cache and returns # them to the current host, yo. class Puppet::Parser::AST -class Collection < AST::Branch - attr_accessor :type, :query, :form - attr_reader :override - - associates_doc - - # We return an object that does a late-binding evaluation. - def evaluate(scope) - if self.query - str, code = self.query.safeevaluate scope - else - str = code = nil - end - - newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form) - - scope.compiler.add_collection(newcoll) - - # overrides if any - # Evaluate all of the specified params. - if @override - params = @override.collect do |param| - param.safeevaluate(scope) + class Collection < AST::Branch + attr_accessor :type, :query, :form + attr_reader :override + + associates_doc + + # We return an object that does a late-binding evaluation. + def evaluate(scope) + str, code = query && query.safeevaluate(scope) + + newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form) + + scope.compiler.add_collection(newcoll) + + # overrides if any + # Evaluate all of the specified params. + if @override + params = @override.collect { |param| param.safeevaluate(scope) } + newcoll.add_override( + :parameters => params, + :file => @file, + :line => @line, + :source => scope.source, + :scope => scope + ) end - - newcoll.add_override( - - :parameters => params, - :file => @file, - :line => @line, - :source => scope.source, - - :scope => scope - ) + newcoll end - newcoll - end - - # Handle our parameter ourselves - def override=(override) - if override.is_a?(AST::ASTArray) - @override = override - else - - @override = AST::ASTArray.new( - - :line => override.line, - :file => override.file, - - :children => [override] - ) + # Handle our parameter ourselves + def override=(override) + @override = if override.is_a?(AST::ASTArray) + override + else + AST::ASTArray.new(:line => override.line,:file => override.file,:children => [override]) + end end end - -end end -- cgit From b2ff6a50202a05f2925fa5046a39ef7f163983f1 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Mon, 15 Nov 2010 19:19:02 -0800 Subject: Fix for #5298 -- Collections need to do type lookup When the responsibility for type-name resolution was moved to the AST nodes in commit 449315a2c705df2396852462a1d1e14774b9f117, at least one instance was missed: the space ship operator Myclass <<| tag == foo |>> fails unless Myclass has been previously loaded. This commit adds the lookup to AST::Collection nodes in the same way it was added to the other node types. Note that I haven't audited the other note types for similar cases. --- lib/puppet/parser/ast/collection.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb index 90a914337..ef36b7143 100644 --- a/lib/puppet/parser/ast/collection.rb +++ b/lib/puppet/parser/ast/collection.rb @@ -15,7 +15,8 @@ class Puppet::Parser::AST def evaluate(scope) str, code = query && query.safeevaluate(scope) - newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form) + resource_type = scope.find_resource_type(@type) + newcoll = Puppet::Parser::Collector.new(scope, resource_type.name, str, code, self.form) scope.compiler.add_collection(newcoll) -- cgit From fbb096a1eb6394da3199c03645986a1315132272 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Wed, 20 Oct 2010 11:33:20 -0700 Subject: Fix for #5055 -- adding to_sym to Puppet::Node::Environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The currious part is that this wasn't noticed before since it appears to block server-first migration to 2.6.x and doesn’t appear to be the consequence of a recent (2.6.3) change (unless, as is quite possible, I’m missing something). --- lib/puppet/node/environment.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb index 3f67474f9..b64fb8a1f 100644 --- a/lib/puppet/node/environment.rb +++ b/lib/puppet/node/environment.rb @@ -124,6 +124,10 @@ class Puppet::Node::Environment name.to_s end + def to_sym + to_s.to_sym + end + # The only thing we care about when serializing an environment is its # identity; everything else is ephemeral and should not be stored or # transmitted. -- cgit From 866205624873d0a6ab17c03061e89d74a3a77019 Mon Sep 17 00:00:00 2001 From: Markus Roberts Date: Fri, 15 Oct 2010 12:43:06 -0700 Subject: Fix for #4279 -- mount detection on HP-UX This is based on the discussion on ticket, simplified slightly and with test adjustment. --- lib/puppet/provider/mount.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/mount.rb b/lib/puppet/provider/mount.rb index 393ae56c9..8c7b24bd4 100644 --- a/lib/puppet/provider/mount.rb +++ b/lib/puppet/provider/mount.rb @@ -41,7 +41,7 @@ module Puppet::Provider::Mount case platform when "Darwin" line =~ / on #{name} / or line =~ %r{ on /private/var/automount#{name}} - when "Solaris" + when "Solaris", "HP-UX" line =~ /^#{name} on / else line =~ / on #{name} / -- cgit From 74b6c09e3b074e0ffc8679dcf31b5fa900020e39 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Mon, 15 Nov 2010 14:24:15 -0800 Subject: (#4726) Fix RRD legacy support There was a section of code that didn't take the legacy RRD library into account. This caused a unit test failure, but only if you have the RRD legacy library installed, which I did. Paired-with: Jesse Wolfe --- lib/puppet/util/metric.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb index 90a244836..8f55e7b44 100644 --- a/lib/puppet/util/metric.rb +++ b/lib/puppet/util/metric.rb @@ -64,7 +64,7 @@ class Puppet::Util::Metric end def graph(range = nil) - unless Puppet.features.rrd? + unless Puppet.features.rrd? || Puppet.features.rrd_legacy? Puppet.warning "RRD library is missing; cannot graph metrics" return end -- cgit From 178c2a628256d22b6bec39ee6f9022b38c9aa4f4 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Mon, 4 Oct 2010 14:01:49 -0700 Subject: Fix test failures that fixing #4726 exposed. The patch for #4726 causes old unit tests of the rrd reporting infrastructure to run on my machine. These tests were calling the old report api, which does not succeed. Also, the rrd settings had unintentionally been moved out of the :metrics section, making it possible that the rrd report directory would fail to get created during testing. --- lib/puppet/defaults.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 93b01c779..4521a5901 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -453,6 +453,12 @@ module Puppet :reporturl => ["http://localhost:3000/reports", "The URL used by the http reports processor to send reports"], :fileserverconfig => ["$confdir/fileserver.conf", "Where the fileserver configuration is stored."], + :strict_hostname_checking => [false, "Whether to only search for the complete + hostname as it is in the certificate when searching for node information + in the catalogs."] + ) + + setdefaults(:metrics, :rrddir => {:default => "$vardir/rrd", :owner => "service", :group => "service", @@ -461,10 +467,7 @@ module Puppet this directory." }, :rrdinterval => ["$runinterval", "How often RRD should expect data. - This should match how often the hosts report back to the server."], - :strict_hostname_checking => [false, "Whether to only search for the complete - hostname as it is in the certificate when searching for node information - in the catalogs."] + This should match how often the hosts report back to the server."] ) setdefaults(:agent, -- cgit From 28e5772d035057e1fe80e6092d8c1b463613e9f8 Mon Sep 17 00:00:00 2001 From: Nigel Kersten Date: Mon, 15 Nov 2010 12:36:34 -0800 Subject: (#5304) Use internal_name rather than real_name for maillist provider We've switched to using list_lists --bare which shows the internal_name rather than "real_name", which is the authoritative identifier. Doing this also means we have less output to scrub, so the code is simpler. Signed-off-by: Nigel Kersten --- lib/puppet/provider/maillist/mailman.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/maillist/mailman.rb b/lib/puppet/provider/maillist/mailman.rb index 4fdc20a69..633642af7 100755 --- a/lib/puppet/provider/maillist/mailman.rb +++ b/lib/puppet/provider/maillist/mailman.rb @@ -2,11 +2,11 @@ require 'puppet/provider/parsedfile' Puppet::Type.type(:maillist).provide(:mailman) do if [ "CentOS", "RedHat", "Fedora" ].any? { |os| Facter.value(:operatingsystem) == os } - commands :list_lists => "/usr/lib/mailman/bin/list_lists", :rmlist => "/usr/lib/mailman/bin/rmlist", :newlist => "/usr/lib/mailman/bin/newlist" + commands :list_lists => "/usr/lib/mailman/bin/list_lists --bare", :rmlist => "/usr/lib/mailman/bin/rmlist", :newlist => "/usr/lib/mailman/bin/newlist" commands :mailman => "/usr/lib/mailman/mail/mailman" else # This probably won't work for non-Debian installs, but this path is sure not to be in the PATH. - commands :list_lists => "list_lists", :rmlist => "rmlist", :newlist => "newlist" + commands :list_lists => "list_lists --bare", :rmlist => "rmlist", :newlist => "newlist" commands :mailman => "/var/lib/mailman/mail/mailman" end @@ -14,10 +14,9 @@ Puppet::Type.type(:maillist).provide(:mailman) do # Return a list of existing mailman instances. def self.instances - list_lists.split("\n").reject { |line| line.include?("matching mailing lists") }.collect do |line| - name, description = line.sub(/^\s+/, '').sub(/\s+$/, '').split(/\s+-\s+/) - description = :absent if description.include?("no description available") - new(:ensure => :present, :name => name, :description => description) + list_lists.split("\n").collect do |line| + name = line.strip + new(:ensure => :present, :name => name) end end -- cgit From ee7d2f92f9d3ec45b5c3a9cd3fe2f5832b17f23b Mon Sep 17 00:00:00 2001 From: Stefan Schulte Date: Wed, 17 Nov 2010 23:15:46 +0100 Subject: (#5274) New comment property for the hosttype When the parsefile provider for host parses /etc/hosts, it throws any inlinecomment away. As a result they are also purged in /etc/hosts after a puppetrun that detects a change. That could be dangerous because you will lose information even about unmanaged resources. So if you have something like 192.168.0.1 hostentry_not_managed_by_puppet # Important comment in /etc/hosts the endresult will be 192.168.0.1\thostentry_not_managed_by_puppet This patch introduces a new property "comment" for the host type. The provider is nearly a complete rewrite and a lot shorter and hopefully easier to understand. --- lib/puppet/provider/host/parsed.rb | 76 ++++++++++++-------------------------- lib/puppet/type/host.rb | 28 +++++--------- 2 files changed, 32 insertions(+), 72 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/host/parsed.rb b/lib/puppet/provider/host/parsed.rb index 4f15eff3f..a303c4bcf 100644 --- a/lib/puppet/provider/host/parsed.rb +++ b/lib/puppet/provider/host/parsed.rb @@ -8,66 +8,36 @@ else end - Puppet::Type.type(:host).provide( - :parsed, - :parent => Puppet::Provider::ParsedFile, - :default_target => hosts, - - :filetype => :flat -) do +Puppet::Type.type(:host).provide(:parsed,:parent => Puppet::Provider::ParsedFile, + :default_target => hosts,:filetype => :flat) do confine :exists => hosts text_line :comment, :match => /^#/ text_line :blank, :match => /^\s*$/ - record_line :parsed, :fields => %w{ip name host_aliases}, - :optional => %w{host_aliases}, - :rts => true do |line| - hash = {} - if line.sub!(/^(\S+)\s+(\S+)\s*/, '') - hash[:ip] = $1 - hash[:name] = $2 - - if line.empty? - hash[:host_aliases] = [] + record_line :parsed, :fields => %w{ip name host_aliases comment}, + :optional => %w{host_aliases comment}, + :match => /^(\S+)\s+(\S+)\s*(.*?)?(?:\s*#\s*(.*))?$/, + :post_parse => proc { |hash| + # An absent comment should match "comment => ''" + hash[:comment] = '' if hash[:comment].nil? or hash[:comment] == :absent + unless hash[:host_aliases].nil? or hash[:host_aliases] == :absent + hash[:host_aliases] = hash[:host_aliases].split(/\s+/) else - line.sub!(/\s*/, '') - line.sub!(/^([^#]+)\s*/) do |value| - aliases = $1 - unless aliases =~ /^\s*$/ - hash[:host_aliases] = aliases.split(/\s+/) - end - - "" - end + hash[:host_aliases] = [] end - else - raise Puppet::Error, "Could not match '#{line}'" - end - - hash[:host_aliases] = [] if hash[:host_aliases] == "" - - return hash - end - - # Convert the current object into a host-style string. - def self.to_line(hash) - return super unless hash[:record_type] == :parsed - [:ip, :name].each do |n| - raise ArgumentError, "#{n} is a required attribute for hosts" unless hash[n] and hash[n] != :absent - end - - str = "#{hash[:ip]}\t#{hash[:name]}" - - if hash.include? :host_aliases and !hash[:host_aliases].empty? - if hash[:host_aliases].is_a? Array + }, + :to_line => proc { |hash| + [:ip, :name].each do |n| + raise ArgumentError, "#{n} is a required attribute for hosts" unless hash[n] and hash[n] != :absent + end + str = "#{hash[:ip]}\t#{hash[:name]}" + if hash.include? :host_aliases and !hash[:host_aliases].empty? str += "\t#{hash[:host_aliases].join("\t")}" - else - raise ArgumentError, "Host aliases must be specified as an array" end - end - - str - end + if hash.include? :comment and !hash[:comment].empty? + str += "\t# #{hash[:comment]}" + end + str + } end - diff --git a/lib/puppet/type/host.rb b/lib/puppet/type/host.rb index 8ab750459..1af74d886 100755 --- a/lib/puppet/type/host.rb +++ b/lib/puppet/type/host.rb @@ -5,11 +5,11 @@ module Puppet newproperty(:ip) do desc "The host's IP address, IPv4 or IPv6." - validate do |value| - unless value =~ /((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})/ - raise Puppet::Error, "Invalid IP address" + validate do |value| + unless value =~ /^((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})$/ + raise Puppet::Error, "Invalid IP address" + end end - end end @@ -26,21 +26,6 @@ module Puppet currentvalue.join(" ") end - def retrieve - is = super - case is - when String - is = is.split(/\s*,\s*/) - when Symbol - is = [is] - when Array - # nothing - else - raise Puppet::DevError, "Invalid @is type #{is.class}" - end - is - end - # We actually want to return the whole array here, not just the first # value. def should @@ -61,9 +46,14 @@ module Puppet validate do |value| raise Puppet::Error, "Host aliases cannot include whitespace" if value =~ /\s/ + raise Puppet::Error, "Host alias cannot be an empty string. Use an empty array to delete all host_aliases " if value =~ /^\s*$/ end end + newproperty(:comment) do + desc "A comment that will be attached to the line with a # character" + end + newproperty(:target) do desc "The file in which to store service information. Only used by those providers that write to disk." -- cgit From cf18353472ce9c4e51157d21882a7f129853fd10 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Thu, 18 Nov 2010 13:21:35 -0800 Subject: Maint: Switched spec tests to use a class rather than Array as the log destination. Using an Array as a log destination is unreliable because Puppet's log mechanism stores log destinations in a hash whose key is the destination itself. Since arrays can change their hash when they are modified, this was causing the log destination hash to become corrupted, producing sporadic spec test failures. --- lib/puppet/util/log/destinations.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util/log/destinations.rb b/lib/puppet/util/log/destinations.rb index 22b3dedb2..2e2f9a5b7 100644 --- a/lib/puppet/util/log/destinations.rb +++ b/lib/puppet/util/log/destinations.rb @@ -203,8 +203,20 @@ Puppet::Util::Log.newdesttype :report do end # Log to an array, just for testing. +module Puppet::Test + class LogCollector + def initialize(logs) + @logs = logs + end + + def <<(value) + @logs << value + end + end +end + Puppet::Util::Log.newdesttype :array do - match "Array" + match "Puppet::Test::LogCollector" def initialize(messages) @messages = messages -- cgit From e8254856a5c9fa532886148cbe2b0f8d87179f01 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Thu, 18 Nov 2010 11:09:46 -0800 Subject: Maint: Added assertion to make sure Log.close_all succeeds If the hash containing log destinations gets corrupted, Log.close_all could fail silently. This change adds an exception to make these failures easier to debug should they ever happen again. --- lib/puppet/util/log.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb index 36a765c61..a5aacc265 100644 --- a/lib/puppet/util/log.rb +++ b/lib/puppet/util/log.rb @@ -57,6 +57,7 @@ class Puppet::Util::Log destinations.keys.each { |dest| close(dest) } + raise Puppet::DevError.new("Log.close_all failed to close #{@destinations.keys.inspect}") if !@destinations.empty? end # Flush any log destinations that support such operations. -- cgit From 32dcb31a7a371ea542bf3c733d3d775ef3a8e51d Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 22 Nov 2010 11:27:37 -0800 Subject: (#5370) Made metrics and --summarize work with Puppet apply Puppet apply and Puppet agent use different code paths to run the transaction. In the code path for Puppet apply, we weren't passing the report to catalog.apply, and as a result catalog.apply was creating its own report to store metrics in; this report was then discarded. As a result, reports generated using "puppet apply" had no metrics, and the "--summarize" option didn't work at all. Fixed by modifying the "puppet apply" code path to pass the report to catalog.apply. In the future it would be nice to refactor the two code paths to be the same. Paired-with: Jesse Wolfe --- lib/puppet/application/apply.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index 59a95d35a..f6299f9fe 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -130,7 +130,7 @@ class Puppet::Application::Apply < Puppet::Application report = configurer.initialize_report Puppet::Util::Log.newdestination(report) end - transaction = catalog.apply + transaction = catalog.apply(:report => report) configurer.execute_postrun_command -- cgit From 4a2bbbcf197760ce2eb3c257742293794d6fb571 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Mon, 22 Nov 2010 14:56:49 -0800 Subject: maint: Fix tests that don't run on their own From the spec directory I found all the specs that fail when run on their own. for TEST in `find . -name "*.rb" -type f`; do spec $TEST > /dev/null 2>&1 if [[ $? != 0 ]]; then echo $TEST fi done All of them were cases of missing requires. Paired-with: Nick Lewis --- lib/puppet/parser/templatewrapper.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb index 73a4ad8aa..6864aa1a9 100644 --- a/lib/puppet/parser/templatewrapper.rb +++ b/lib/puppet/parser/templatewrapper.rb @@ -1,6 +1,7 @@ # A simple wrapper for templates, so they don't have full access to # the scope objects. require 'puppet/parser/files' +require 'erb' class Puppet::Parser::TemplateWrapper attr_writer :scope -- cgit From 095675711a89d836f4d0f10978ed5759b93fe76f Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Mon, 22 Nov 2010 15:17:51 -0800 Subject: Fix #5261 Don't escape Unicode characters in PSON This patch removes the escaping of valid UTF-8 sequences as "\uXXXX". This code was unreliable, as it relied on Iconv's ability to convert those codepoints between UTF-8 and UTF-16, but some versions of Iconv barf on some valid codepoints. Invalid UTF-8 sequences are still passed through unchanged. We believe that this is fine; if you are concerned about complience with the JSON standard, what we are doing is equivalent to: * interpreting binary files as Latin-1 encoded character sequences * JSON-encoding those characters according to RFC 4627 * outputting the JSON as Latin-1 This allows all raw binary files to be transmitted losslessly. Paired-With: Paul Berry --- lib/puppet/external/pson/pure/generator.rb | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/external/pson/pure/generator.rb b/lib/puppet/external/pson/pure/generator.rb index 4180be57d..89a0c62e0 100644 --- a/lib/puppet/external/pson/pure/generator.rb +++ b/lib/puppet/external/pson/pure/generator.rb @@ -44,34 +44,13 @@ module PSON string << '' # XXX workaround: avoid buffer sharing string.force_encoding(Encoding::ASCII_8BIT) string.gsub!(/["\\\x0-\x1f]/) { MAP[$MATCH] } - string.gsub!(/( - (?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+ | - [\x80-\xc1\xf5-\xff] # invalid - )/nx) { |c| - c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" - s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0] - s.gsub!(/.{4}/n, '\\\\u\&') - } - string.force_encoding(Encoding::UTF_8) string rescue Iconv::Failure => e raise GeneratorError, "Caught #{e.class}: #{e}" end else def utf8_to_pson(string) # :nodoc: - string. - gsub(/["\\\x0-\x1f]/n) { MAP[$MATCH] }. - gsub(/((?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+)/nx) { |c| - PSON::UTF8toUTF16.iconv(c).unpack('H*')[0].gsub(/.{4}/n, '\\\\u\&') - } + string.gsub(/["\\\x0-\x1f]/n) { MAP[$MATCH] } end end module_function :utf8_to_pson -- cgit From 9ccd29f3aacdab03f2ea9a693b5bca928439683b Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Tue, 7 Sep 2010 18:06:09 -0400 Subject: (#2866) yum should support downgrade. patch originally from Grzegorz Nosek with contributions on the test from Oliver Hookins. checks if the current version is greater than the should version, if so, calls yum downgrade. Reviewed-by: Matt Robinson --- lib/puppet/provider/package/yum.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb index fcda5ba8c..6ed966fbd 100755 --- a/lib/puppet/provider/package/yum.rb +++ b/lib/puppet/provider/package/yum.rb @@ -1,3 +1,4 @@ +require 'puppet/util/package' Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do desc "Support via `yum`." @@ -52,6 +53,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do should = @resource.should(:ensure) self.debug "Ensuring => #{should}" wanted = @resource[:name] + operation = :install # XXX: We don't actually deal with epochs here. case should @@ -61,9 +63,14 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do else # Add the package version wanted += "-#{should}" + is = self.query + if is && Puppet::Util::Package.versioncmp(should, is[:ensure]) < 0 + self.debug "Downgrading package #{@resource[:name]} from version #{is[:ensure]} to #{should}" + operation = :downgrade + end end - output = yum "-d", "0", "-e", "0", "-y", :install, wanted + output = yum "-d", "0", "-e", "0", "-y", operation, wanted is = self.query raise Puppet::Error, "Could not find package #{self.name}" unless is -- cgit From 3a815e191837f9fc1fb7b6621be607225347f014 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 23 Nov 2010 11:47:36 -0800 Subject: (#5375) Rework puppet apply to use configurer.run Puppet apply used to contain code that duplicated the functionality of configurer.run. Refactored to share code. Paired-with: Jesse Wolfe --- lib/puppet/application/apply.rb | 21 ++------------------- lib/puppet/configurer.rb | 8 ++++---- 2 files changed, 6 insertions(+), 23 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index 32a6b65b9..8ec3fab6b 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -123,26 +123,9 @@ class Puppet::Application::Apply < Puppet::Application require 'puppet/configurer' configurer = Puppet::Configurer.new - configurer.execute_prerun_command + report = configurer.run(:skip_plugin_download => true, :catalog => catalog) - # And apply it - if Puppet[:report] - report = configurer.initialize_report - Puppet::Util::Log.newdestination(report) - end - transaction = catalog.apply(:report => report) - - configurer.execute_postrun_command - - if Puppet[:report] - Puppet::Util::Log.close(report) - configurer.send_report(report, transaction) - else - transaction.generate_report - configurer.save_last_run_summary(transaction.report) - end - - exit( Puppet[:noop] ? 0 : options[:detailed_exitcodes] ? transaction.report.exit_status : 0 ) + exit( Puppet[:noop] ? 0 : options[:detailed_exitcodes] ? report.exit_status : 0 ) rescue => detail puts detail.backtrace if Puppet[:trace] $stderr.puts detail.message diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb index e46e9a6e7..1c0639029 100644 --- a/lib/puppet/configurer.rb +++ b/lib/puppet/configurer.rb @@ -77,12 +77,12 @@ class Puppet::Configurer end # Prepare for catalog retrieval. Downloads everything necessary, etc. - def prepare + def prepare(options) dostorage - download_plugins + download_plugins unless options[:skip_plugin_download] - download_fact_plugins + download_fact_plugins unless options[:skip_plugin_download] execute_prerun_command end @@ -126,7 +126,7 @@ class Puppet::Configurer # which accepts :tags and :ignoreschedules. def run(options = {}) begin - prepare + prepare(options) rescue SystemExit,NoMemoryError raise rescue Exception => detail -- cgit