summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/compiler.rb
Commit message (Collapse)AuthorAgeFilesLines
* (#5045) Cleaning up some tests and codeMatt Robinson2011-01-241-1/+1
| | | | | | | Renamed some variables to be clearer, made tests use less stubbing, added some additional tests and got rid of some unecessary logic. Paired-with: Dan Bode
* (#5045) External node classifiers should be able to specify params for classesDan Bode2011-01-241-3/+18
| | | | | | | | | | It facilitates the support for param classes from the ENC. It adds support for classes to be passed as a hash to the evaluate_classes method. If a hash of classes is specified, it also evaluates duplicates. I also had to convert the hash to an array for tags to be applied correctly. Reviewed-by: Matt Robinson
* (#4534/#4778) -- Normalize parameterized classesPaul Berry2010-10-271-2/+2
| | | | | | | | | | | | | | | | | | | This is a reconciliation/melding of Paul's (#4534) Class inheritance with parameterized classes is no longer ignored and Markus's Fix for #4778 -- evaluate parameterized classes when they are instantiated Extracted the code from Resource::Type#mk_plain_resource that evaluates parents and tags the catalog, and moved that into a new method called instantiate_resource. Instantiate_resource is now also called from Parser::Ast::Resource#evaluate, so that the notation "class { classname: }" now executes this code too. Likewise adds class evaluation so that it behaves the same (with regard to lazy / strict evaluation) as include classname
* Fix for #4693 -- implicit stages should never be serializedMarkus Roberts2010-09-071-1/+1
| | | | | | | | | | | My fix for #4542 was overly enthusiastic about assuring that all resources had a stage, resulting in stages designations being serialized for resources in manifests which did not use resources (everything was in implicit main). This broke 0.25.x compatibility, as all catalogs now refered to stages. This patch scales back the change for #4542 slightly, supressing the setting of main on the puppetmaster and relying on the default behaviour on the client (for 2.6.x and later, treat it as main; for 0.25.x, do nothing).
* Fix for #4542 -- included classes weren't assigned proper stagesMarkus Roberts2010-08-241-13/+6
| | | | | | This commit unifies the code paths on which classes are added, alters the default stage to respect the stage of the parent if any, and assures that the resource is notified if its stage is assigned (turning an implicit stage into an explicit one).
* Fix #4461 - attempt to fix another performance issueBrice Figureau2010-08-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | During a profiling of a 2.6.1rc1 puppet master, I found that we spend a lot of time and efforts in Puppet::Util::Autoload#module_directories. Since this method is doing a bunch of filesystem access, this process is slow. In fact each time we were evaluating a resource or trying to find if a given resource was a builtin type we ended up scanning the whole module directories for the given environment. This patch attempts to fix this performance issue by caching the module_directories output for the either the time of the compilation or an agent configurer run (since this stuff looks like to be shared for both compilation and catalog evaluation). With this patch, my compilation time for 2k resources went from 5.91s to 3.71s (second run each time to allievate parsing time).. Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com> Edited to fix a typo [#4434] Signed-off-by: Jesse Wolfe <jes5199@gmail.com>
* Tweak to fix for #4302--dangling ref to known_resource_typesMarkus Roberts2010-07-251-6/+5
| | | | | | | | | | | | | | | | Since we were clearing the thread variable containing the compiler's reference to it's environment's known resource types at the start of each compile the reference remaining at the end of a compilation could never be used and was thus just garbage that we were arbitrarily retaining. This patch moves the clearing of the thread var to the _end_ of compilation so that it's always nil except in the middle of a compile. This raises an interesting question; should the ref just live on the compiler object and we could dispense with the thread-var? It might require things that now only know about the environment to need a ref to the compiler and introduce other thread issues (e.g. we might just end up needing a :current_compiler thread variable, for no net gain in simplicity).
* Fix #4302 - Compilation speed regression compared to 2.6Brice Figureau2010-07-251-0/+5
| | | | | | | | | | | | | | | | | | | | | Each time the compiler was accessing the loaded types, we were checking if the manifests had changed. This incurred a large performance cost compared to 0.25 and introduced race conditions if manifests changed while a thread was in the middle of a compilation. This tentative fix, based on Brice's, makes sure each thread will get access to the same loaded types collection for the durration of a compilation, even if the manifests change. We now only check for changed files at the start of a compilation or if the environment changes, and we maintain a per environment thread lock so that only one thread at a time can be reloading any particular environment (and the need-check is done inside the synchronize block so that only the first will actually load it). As long as the manifests don't change, the threads will share the same collection, so there is only duplication in memory for a brief window surrounding a change. Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com> Second-author: Markus Roberts <markus@puppetlabs.com>
* Partial fix for #4278 -- the performance aspectsMarkus Roberts2010-07-181-20/+3
| | | | | | | | | unevaluated_resources was a performance bottleneck and was doing a great deal of unneeded work, such as searching for the type of evaluated resources before ignoring them because only unevaluated resources were wanted. This patch is behaviour neutral but gives a 2-3x speedup for compiles with many defined resources.
* Code smell: Two space indentationMarkus Roberts2010-07-091-411/+411
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Replaced 106806 occurances of ^( +)(.*$) with The ruby community almost universally (i.e. everyone but Luke, Markus, and the other eleven people who learned ruby in the 1900s) uses two-space indentation. 3 Examples: The code: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") becomes: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") The code: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object becomes: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object The code: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end becomes: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end
* Code smell: Avoid needless decorationsMarkus Roberts2010-07-091-9/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replaced 704 occurances of (.*)\b([a-z_]+)\(\) with \1\2 3 Examples: The code: ctx = OpenSSL::SSL::SSLContext.new() becomes: ctx = OpenSSL::SSL::SSLContext.new The code: skip() becomes: skip The code: path = tempfile() becomes: path = tempfile * Replaced 31 occurances of ^( *)end *#.* with \1end 3 Examples: The code: becomes: The code: end # Dir.foreach becomes: end The code: end # def becomes: end
* Code smell: Avoid explicit returnsMarkus Roberts2010-07-091-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Replaced 583 occurances of (DEF) (LINES) return (.*) end with 3 Examples: The code: def consolidate_failures(failed) filters = Hash.new { |h,k| h[k] = [] } failed.each do |spec, failed_trace| if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } filters[f] << spec break end end return filters end becomes: def consolidate_failures(failed) filters = Hash.new { |h,k| h[k] = [] } failed.each do |spec, failed_trace| if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } filters[f] << spec break end end filters end The code: def retrieve return_value = super return_value = return_value[0] if return_value && return_value.is_a?(Array) return return_value end becomes: def retrieve return_value = super return_value = return_value[0] if return_value && return_value.is_a?(Array) return_value end The code: def fake_fstab os = Facter['operatingsystem'] if os == "Solaris" name = "solaris.fstab" elsif os == "FreeBSD" name = "freebsd.fstab" else # Catchall for other fstabs name = "linux.fstab" end oldpath = @provider_class.default_target return fakefile(File::join("data/types/mount", name)) end becomes: def fake_fstab os = Facter['operatingsystem'] if os == "Solaris" name = "solaris.fstab" elsif os == "FreeBSD" name = "freebsd.fstab" else # Catchall for other fstabs name = "linux.fstab" end oldpath = @provider_class.default_target fakefile(File::join("data/types/mount", name)) end
* Code smell: Booleans are first class values.Markus Roberts2010-07-091-5/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replaced 2 occurances of def (.*) begin (.*) = Integer\((.*)\) return \2 rescue ArgumentError \2 = nil end if \2 = (.*) return \2 else return false end end with 2 Examples: The code: def validuser?(value) begin number = Integer(value) return number rescue ArgumentError number = nil end if number = uid(value) return number else return false end end becomes: def validuser?(value) Integer(value) rescue uid(value) || false end The code: def validgroup?(value) begin number = Integer(value) return number rescue ArgumentError number = nil end if number = gid(value) return number else return false end end becomes: def validgroup?(value) Integer(value) rescue gid(value) || false end * Replaced 28 occurances of return (.*?) if (.*) return (.*) with 3 Examples: The code: return send(options[:mode]) if [:rdoc, :trac, :markdown].include?(options[:mode]) return other becomes: return[:rdoc, :trac, :markdown].include?(options[:mode]) ? send(options[:mode]) : other The code: return true if known_resource_types.definition(name) return false becomes: return(known_resource_types.definition(name) ? true : false) The code: return :rest if request.protocol == 'https' return Puppet::FileBucket::File.indirection.terminus_class becomes: return(request.protocol == 'https' ? :rest : Puppet::FileBucket::File.indirection.terminus_class) * Replaced no occurances of return (.*?) unless (.*) return (.*) with * Replaced 7 occurances of if (.*) (.*[^:])false else \2true end with 3 Examples: The code: if RUBY_PLATFORM == "i386-mswin32" InstallOptions.ri = false else InstallOptions.ri = true end becomes: InstallOptions.ri = RUBY_PLATFORM != "i386-mswin32" The code: if options[:references].length > 1 with_contents = false else with_contents = true end becomes: with_contents = options[:references].length <= 1 The code: if value == false or value == "" or value == :undef return false else return true end becomes: return (value != false and value != "" and value != :undef) * Replaced 19 occurances of if (.*) (.*[^:])true else \2false end with 3 Examples: The code: if Puppet::Util::Log.level == :debug return true else return false end becomes: return Puppet::Util::Log.level == :debug The code: if satisfies?(*features) return true else return false end becomes: return !!satisfies?(*features) The code: if self.class.parsed_auth_db.has_key?(resource[:name]) return true else return false end becomes: return !!self.class.parsed_auth_db.has_key?(resource[:name]) * Replaced 1 occurance of if ([a-z_]) = (.*) (.*[^:])\1 else \3(.*) end with 1 Example: The code: if c = self.send(@subclassname, method) return c else return nil end becomes: return self.send(@subclassname, method) || nil * Replaced 2 occurances of if (.*) (.*[^:])\1 else \2false end with 2 Examples: The code: if hash[:Local] @local = hash[:Local] else @local = false end becomes: @local = hash[:Local] The code: if hash[:Local] @local = hash[:Local] else @local = false end becomes: @local = hash[:Local] * Replaced 10 occurances of if (.*) (.*[^:])(.*) else \2false end with 3 Examples: The code: if defined?(@isnamevar) return @isnamevar else return false end becomes: return defined?(@isnamevar) && @isnamevar The code: if defined?(@required) return @required else return false end becomes: return defined?(@required) && @required The code: if number = uid(value) return number else return false end becomes: return (number = uid(value)) && number * Replaced no occurances of if (.*) (.*[^:])nil else \2(true) end with * Replaced no occurances of if (.*) (.*[^:])true else \2nil end with * Replaced no occurances of if (.*) (.*[^:])\1 else \2nil end with * Replaced 23 occurances of if (.*) (.*[^:])(.*) else \2nil end with 3 Examples: The code: if node = Puppet::Node.find(hostname) env = node.environment else env = nil end becomes: env = (node = Puppet::Node.find(hostname)) ? node.environment : nil The code: if mod = Puppet::Node::Environment.new(env).module(module_name) and mod.files? return @mounts[MODULES].copy(mod.name, mod.file_directory) else return nil end becomes: return (mod = Puppet::Node::Environment.new(env).module(module_name) and mod.files?) ? @mounts[MODULES].copy(mod.name, mod.file_directory) : nil The code: if hash.include?(:CA) and hash[:CA] @ca = Puppet::SSLCertificates::CA.new() else @ca = nil end becomes: @ca = (hash.include?(:CA) and hash[:CA]) ? Puppet::SSLCertificates::CA.new() : nil
* Code smell: Line modifiers are preferred to one-line blocks.Markus Roberts2010-07-091-9/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replaced 6 occurances of (while .*?) *do$ with The do is unneeded in the block header form and causes problems with the block-to-one-line transformation. 3 Examples: The code: while line = f.gets do becomes: while line = f.gets The code: while line = shadow.gets do becomes: while line = shadow.gets The code: while wrapper = zeros.pop do becomes: while wrapper = zeros.pop * Replaced 19 occurances of ((if|unless) .*?) *then$ with The then is unneeded in the block header form and causes problems with the block-to-one-line transformation. 3 Examples: The code: if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } then becomes: if f = test_files_for(failed).find { |f| failed_trace =~ Regexp.new(f) } The code: unless defined?(@spec_command) then becomes: unless defined?(@spec_command) The code: if c == ?\n then becomes: if c == ?\n * Replaced 758 occurances of ((?:if|unless|while|until) .*) (.*) end with The one-line form is preferable provided: * The condition is not used to assign a variable * The body line is not already modified * The resulting line is not too long 3 Examples: The code: if Puppet.features.libshadow? has_feature :manages_passwords end becomes: has_feature :manages_passwords if Puppet.features.libshadow? The code: unless (defined?(@current_pool) and @current_pool) @current_pool = process_zpool_data(get_pool_data) end becomes: @current_pool = process_zpool_data(get_pool_data) unless (defined?(@current_pool) and @current_pool) The code: if Puppet[:trace] puts detail.backtrace end becomes: puts detail.backtrace if Puppet[:trace]
* Code smell: Use string interpolationMarkus Roberts2010-07-091-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replaced 83 occurances of (.*)" *[+] *([$@]?[\w_0-9.:]+?)(.to_s\b)?(?! *[*(%\w_0-9.:{\[]) with \1#{\2}" 3 Examples: The code: puts "PUPPET " + status + ": " + process + ", " + state becomes: puts "PUPPET " + status + ": " + process + ", #{state}" The code: puts "PUPPET " + status + ": #{process}" + ", #{state}" becomes: puts "PUPPET #{status}" + ": #{process}" + ", #{state}" The code: }.compact.join( "\n" ) + "\n" + t + "]\n" becomes: }.compact.join( "\n" ) + "\n#{t}" + "]\n" * Replaced 21 occurances of (.*)" *[+] *" with \1 3 Examples: The code: puts "PUPPET #{status}" + ": #{process}" + ", #{state}" becomes: puts "PUPPET #{status}" + ": #{process}, #{state}" The code: puts "PUPPET #{status}" + ": #{process}, #{state}" becomes: puts "PUPPET #{status}: #{process}, #{state}" The code: res = self.class.name + ": #{@name}" + "\n" becomes: res = self.class.name + ": #{@name}\n" * Don't use string concatenation to split lines unless they would be very long. Replaced 11 occurances of (.*)(['"]) *[+] *(['"])(.*) with 3 Examples: The code: o.define_head "The check_puppet Nagios plug-in checks that specified " + "Puppet process is running and the state file is no " + becomes: o.define_head "The check_puppet Nagios plug-in checks that specified Puppet process is running and the state file is no " + The code: o.separator "Mandatory arguments to long options are mandatory for " + "short options too." becomes: o.separator "Mandatory arguments to long options are mandatory for short options too." The code: o.define_head "The check_puppet Nagios plug-in checks that specified Puppet process is running and the state file is no " + "older than specified interval." becomes: o.define_head "The check_puppet Nagios plug-in checks that specified Puppet process is running and the state file is no older than specified interval." * Replaced no occurances of do (.*?) end with {\1} * Replaced 1488 occurances of "([^"\n]*%s[^"\n]*)" *% *(.+?)(?=$| *\b(do|if|while|until|unless|#)\b) with 20 Examples: The code: args[0].split(/\./).map do |s| "dc=%s"%[s] end.join(",") becomes: args[0].split(/\./).map do |s| "dc=#{s}" end.join(",") The code: puts "%s" % Puppet.version becomes: puts "#{Puppet.version}" The code: raise "Could not find information for %s" % node becomes: raise "Could not find information for #{node}" The code: raise Puppet::Error, "Cannot create %s: basedir %s is a file" % [dir, File.join(path)] becomes: raise Puppet::Error, "Cannot create #{dir}: basedir #{File.join(path)} is a file" The code: Puppet.err "Could not run %s: %s" % [client_class, detail] becomes: Puppet.err "Could not run #{client_class}: #{detail}" The code: raise "Could not find handler for %s" % arg becomes: raise "Could not find handler for #{arg}" The code: Puppet.err "Will not start without authorization file %s" % Puppet[:authconfig] becomes: Puppet.err "Will not start without authorization file #{Puppet[:authconfig]}" The code: raise Puppet::Error, "Could not deserialize catalog from pson: %s" % detail becomes: raise Puppet::Error, "Could not deserialize catalog from pson: #{detail}" The code: raise "Could not find facts for %s" % Puppet[:certname] becomes: raise "Could not find facts for #{Puppet[:certname]}" The code: raise ArgumentError, "%s is not readable" % path becomes: raise ArgumentError, "#{path} is not readable" The code: raise ArgumentError, "Invalid handler %s" % name becomes: raise ArgumentError, "Invalid handler #{name}" The code: debug "Executing '%s' in zone %s with '%s'" % [command, @resource[:name], str] becomes: debug "Executing '#{command}' in zone #{@resource[:name]} with '#{str}'" The code: raise Puppet::Error, "unknown cert type '%s'" % hash[:type] becomes: raise Puppet::Error, "unknown cert type '#{hash[:type]}'" The code: Puppet.info "Creating a new certificate request for %s" % Puppet[:certname] becomes: Puppet.info "Creating a new certificate request for #{Puppet[:certname]}" The code: "Cannot create alias %s: object already exists" % [name] becomes: "Cannot create alias #{name}: object already exists" The code: return "replacing from source %s with contents %s" % [metadata.source, metadata.checksum] becomes: return "replacing from source #{metadata.source} with contents #{metadata.checksum}" The code: it "should have a %s parameter" % param do becomes: it "should have a #{param} parameter" do The code: describe "when registring '%s' messages" % log do becomes: describe "when registring '#{log}' messages" do The code: paths = %w{a b c d e f g h}.collect { |l| "/tmp/iteration%stest" % l } becomes: paths = %w{a b c d e f g h}.collect { |l| "/tmp/iteration#{l}test" } The code: assert_raise(Puppet::Error, "Check '%s' did not fail on false" % check) do becomes: assert_raise(Puppet::Error, "Check '#{check}' did not fail on false") do
* Code smell: Inconsistent indentation and related formatting issuesMarkus Roberts2010-07-091-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replaced 163 occurances of defined\? +([@a-zA-Z_.0-9?=]+) with defined?(\1) This makes detecting subsequent patterns easier. 3 Examples: The code: if ! defined? @parse_config becomes: if ! defined?(@parse_config) The code: return @option_parser if defined? @option_parser becomes: return @option_parser if defined?(@option_parser) The code: if defined? @local and @local becomes: if defined?(@local) and @local * Eliminate trailing spaces. Replaced 428 occurances of ^(.*?) +$ with \1 1 file was skipped. test/ral/providers/host/parsed.rb because 0 * Replace leading tabs with an appropriate number of spaces. Replaced 306 occurances of ^(\t+)(.*) with Tabs are not consistently expanded in all environments. * Don't arbitrarily wrap on sprintf (%) operator. Replaced 143 occurances of (.*['"] *%) +(.*) with Splitting the line does nothing to aid clarity and hinders further refactorings. 3 Examples: The code: raise Puppet::Error, "Cannot create %s: basedir %s is a file" % [dir, File.join(path)] becomes: raise Puppet::Error, "Cannot create %s: basedir %s is a file" % [dir, File.join(path)] The code: Puppet.err "Will not start without authorization file %s" % Puppet[:authconfig] becomes: Puppet.err "Will not start without authorization file %s" % Puppet[:authconfig] The code: $stderr.puts "Could not find host for PID %s with status %s" % [pid, $?.exitstatus] becomes: $stderr.puts "Could not find host for PID %s with status %s" % [pid, $?.exitstatus] * Don't break short arrays/parameter list in two. Replaced 228 occurances of (.*) +(.*) with 3 Examples: The code: puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true) becomes: puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true) The code: assert(FileTest.exists?(daily), "Did not make daily graph for %s" % type) becomes: assert(FileTest.exists?(daily), "Did not make daily graph for %s" % type) The code: assert(prov.target_object(:first).read !~ /^notdisk/, "Did not remove thing from disk") becomes: assert(prov.target_object(:first).read !~ /^notdisk/, "Did not remove thing from disk") * If arguments must wrap, treat them all equally Replaced 510 occurances of lines ending in things like ...(foo, or ...(bar(1,3), with \1 \2 3 Examples: The code: midscope.to_hash(false), becomes: assert_equal( The code: botscope.to_hash(true), becomes: # bottomscope, then checking that we see the right stuff. The code: :path => link, becomes: * Replaced 4516 occurances of ^( *)(.*) with The present code base is supposed to use four-space indentation. In some places we failed to maintain that standard. These should be fixed regardless of the 2 vs. 4 space question. 15 Examples: The code: def run_comp(cmd) puts cmd results = [] old_sync = $stdout.sync $stdout.sync = true line = [] begin open("| #{cmd}", "r") do |f| until f.eof? do c = f.getc becomes: def run_comp(cmd) puts cmd results = [] old_sync = $stdout.sync $stdout.sync = true line = [] begin open("| #{cmd}", "r") do |f| until f.eof? do c = f.getc The code: 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 = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] } string.gsub!(/( becomes: 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 = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] } string.gsub!(/( The code: end } rvalues: rvalue | rvalues comma rvalue { if val[0].instance_of?(AST::ASTArray) result = val[0].push(val[2]) else result = ast AST::ASTArray, :children => [val[0],val[2]] end } becomes: end } rvalues: rvalue | rvalues comma rvalue { if val[0].instance_of?(AST::ASTArray) result = val[0].push(val[2]) else result = ast AST::ASTArray, :children => [val[0],val[2]] end } The code: #passwdproc = proc { @password } keytext = @key.export( OpenSSL::Cipher::DES.new(:EDE3, :CBC), @password ) File.open(@keyfile, "w", 0400) { |f| f << keytext } becomes: # passwdproc = proc { @password } keytext = @key.export( OpenSSL::Cipher::DES.new(:EDE3, :CBC), @password ) File.open(@keyfile, "w", 0400) { |f| f << keytext } The code: end def to_manifest "%s { '%s':\n%s\n}" % [self.type.to_s, self.name, @params.collect { |p, v| if v.is_a? Array " #{p} => [\'#{v.join("','")}\']" else " #{p} => \'#{v}\'" end }.join(",\n") becomes: end def to_manifest "%s { '%s':\n%s\n}" % [self.type.to_s, self.name, @params.collect { |p, v| if v.is_a? Array " #{p} => [\'#{v.join("','")}\']" else " #{p} => \'#{v}\'" end }.join(",\n") The code: via the augeas tool. Requires: - augeas to be installed (http://www.augeas.net) - ruby-augeas bindings Sample usage with a string:: augeas{\"test1\" : context => \"/files/etc/sysconfig/firstboot\", changes => \"set RUN_FIRSTBOOT YES\", becomes: via the augeas tool. Requires: - augeas to be installed (http://www.augeas.net) - ruby-augeas bindings Sample usage with a string:: augeas{\"test1\" : context => \"/files/etc/sysconfig/firstboot\", changes => \"set RUN_FIRSTBOOT YES\", The code: names.should_not be_include("root") end describe "when generating a purgeable resource" do it "should be included in the generated resources" do Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource] @resources.generate.collect { |r| r.ref }.should include(@purgeable_resource.ref) end end describe "when the instance's do not have an ensure property" do becomes: names.should_not be_include("root") end describe "when generating a purgeable resource" do it "should be included in the generated resources" do Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource] @resources.generate.collect { |r| r.ref }.should include(@purgeable_resource.ref) end end describe "when the instance's do not have an ensure property" do The code: describe "when the instance's do not have an ensure property" do it "should not be included in the generated resources" do @no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo') Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource] @resources.generate.collect { |r| r.ref }.should_not include(@no_ensure_resource.ref) end end describe "when the instance's ensure property does not accept absent" do it "should not be included in the generated resources" do @no_absent_resource = Puppet::Type.type(:service).new(:name => 'foobar') becomes: describe "when the instance's do not have an ensure property" do it "should not be included in the generated resources" do @no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo') Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource] @resources.generate.collect { |r| r.ref }.should_not include(@no_ensure_resource.ref) end end describe "when the instance's ensure property does not accept absent" do it "should not be included in the generated resources" do @no_absent_resource = Puppet::Type.type(:service).new(:name => 'foobar') The code: func = nil assert_nothing_raised do func = Puppet::Parser::AST::Function.new( :name => "template", :ftype => :rvalue, :arguments => AST::ASTArray.new( :children => [stringobj(template)] ) becomes: func = nil assert_nothing_raised do func = Puppet::Parser::AST::Function.new( :name => "template", :ftype => :rvalue, :arguments => AST::ASTArray.new( :children => [stringobj(template)] ) The code: assert( @store.allowed?("hostname.madstop.com", "192.168.1.50"), "hostname not allowed") assert( ! @store.allowed?("name.sub.madstop.com", "192.168.0.50"), "subname name allowed") becomes: assert( @store.allowed?("hostname.madstop.com", "192.168.1.50"), "hostname not allowed") assert( ! @store.allowed?("name.sub.madstop.com", "192.168.0.50"), "subname name allowed") The code: assert_nothing_raised { server = Puppet::Network::Handler.fileserver.new( :Local => true, :Config => false ) } becomes: assert_nothing_raised { server = Puppet::Network::Handler.fileserver.new( :Local => true, :Config => false ) } The code: 'yay', { :failonfail => false, :uid => @user.uid, :gid => @user.gid } ).returns('output') output = Puppet::Util::SUIDManager.run_and_capture 'yay', @user.uid, @user.gid becomes: 'yay', { :failonfail => false, :uid => @user.uid, :gid => @user.gid } ).returns('output') output = Puppet::Util::SUIDManager.run_and_capture 'yay', @user.uid, @user.gid The code: ).times(1) pkg.provider.expects( :aptget ).with( '-y', '-q', 'remove', 'faff' becomes: ).times(1) pkg.provider.expects( :aptget ).with( '-y', '-q', 'remove', 'faff' The code: johnny one two billy three four\n" # Just parse and generate, to make sure it's isomorphic. assert_nothing_raised do assert_equal(text, @parser.to_file(@parser.parse(text)), "parsing was not isomorphic") end end def test_valid_attrs becomes: johnny one two billy three four\n" # Just parse and generate, to make sure it's isomorphic. assert_nothing_raised do assert_equal(text, @parser.to_file(@parser.parse(text)), "parsing was not isomorphic") end end def test_valid_attrs The code: "testing", :onboolean => [true, "An on bool"], :string => ["a string", "A string arg"] ) result = [] should = [] assert_nothing_raised("Add args failed") do @config.addargs(result) end @config.each do |name, element| becomes: "testing", :onboolean => [true, "An on bool"], :string => ["a string", "A string arg"] ) result = [] should = [] assert_nothing_raised("Add args failed") do @config.addargs(result) end @config.each do |name, element|
* Fix for #2807 Puppet settings available as variablesMarkus Roberts2010-07-071-1/+21
| | | | | | | This is Luke's patch plus a change to fix a test that it broke. It creates a new sub-scope off the top scope, called "settings" and adds each of the environment's settings to it as variables, thus satisfying the ticket while taking us one step further from being able to implement futures. *sigh*
* Part 2 of fix for #1175 (functions in environments)Markus Roberts2010-02-171-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Jesse and I are shooting for the minimal viable fix here, with the idea that a great deal of refactoring is needed but isn't appropriate at this time. The changes in this commit are: * Index the function-holding modules by environment * We need to know the "current environment" when we're defining a function so we can attach it to the proper module, and this information isn't dynamically available when user-defined functions are being created (we're being called by user written code that doesn't "know" about environments) so we cheat and stash the value in Puppet::Node::Environment * since we must do this anyway, it turns out to be cleaner & safer to do the same when we are evaluating a functon. This is the main change from the prior version of this patch. * Add a special *root* environment for the built in functions, and extend all scopes with it. * Index the function characteristics (name, type, docstring, etc.) by environment * Make the autoloader environment aware, so that it uses the modulepath for the specified environment rather than the default * Turn off caching of the modulepath since it potentially changes for each node * Tweak tests that weren't environment aware
* [#1621] Composite keys for resourcesJesse Wolfe2010-06-211-1/+1
| | | | | | | | | | | | | | | | This patch implements the fundamental pieces of the move to composite keys: * Instead of having a single namevar, we have a non-empty collection of them, and two resources are the same if and only if all of them match. Note that the present situation is a special case of this, where the collection always has exactly one member. * As currently, namevar is determined by the type. * Instead just of inferring the single namevar from the title we let types decompose the title into values for several (perhaps all) of the namevar components; note that the present situation is again a special case of this. Signed-off-by: Jesse Wolfe <jes5199@gmail.com>
* Fixing #2658 - adding backward compatibility for 0.24Luke Kanies2010-02-171-3/+5
| | | | | | | | | | | | | The way stages were implemented caused backward compatibility to be completely broken for 0.24.x. This commit fixes that, mostly by assuming Stage[main] will be the top node in the graph rather than Class[main]. Other stages are not supported in 0.24.x, and explicitly throw a warning (although not an error). Signed-off-by: Luke Kanies <luke@puppetlabs.com>
* Adding #2658 - Adding support for run stagesLuke Kanies2010-02-171-14/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | This allows you to specify a run stage for either a class or a resource. By default, all classes get directly added to the 'main' stage. You can create new stages as resources: stage { [pre, post]: } To order stages, use standard relationships: stage { pre: before => Stage[main] } Or use the new relationship syntax: stage { pre: } -> Stage[main] -> stage { post: } Then use the new class parameters to specify a stage: class { foo: stage => pre } If you set a stage on an individual resource, it will fail; stages can only be set on class resources. Signed-off-by: Luke Kanies <luke@puppetlabs.com>
* Fixing #1903 - metaparam inheritance is much fasterLuke Kanies2010-02-171-0/+44
| | | | | | | | | | | | This doesn't actually fix the specific request in #1903, which said there should be no inheritance at all, but I've changed my mind on that. Static inheritance is good, it should just be faster. This change could result in up to 70% speed improvements in compiling. Signed-off-by: Luke Kanies <luke@puppetlabs.com>
* Fixing #448 - relationships have their own syntaxLuke Kanies2010-02-171-1/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | You can now specify relationships directly in the language: File[/foo] -> Service[bar] Specifies a normal dependency while: File[/foo] ~> Service[bar] Specifies a subscription. You can also do relationship chaining, specifying multiple relationships on a single line: File[/foo] -> Package[baz] -> Service[bar] Note that while it's confusing, you don't have to have all of the arrows be the same direction: File[/foo] -> Service[bar] <~ Package[baz] This can provide some succinctness at the cost of readability. You can also specify full resources, rather than just resource refs: file { "/foo": ensure => present } -> package { bar: ensure => installed } But wait! There's more! You can also specify a subscription on either side of the relationship marker: yumrepo { foo: .... } package { bar: provider => yum, ... } Yumrepo <| |> -> Package <| provider == yum |> This, finally, provides easy many to many relationships in Puppet, but it also opens the door to massive dependency cycles. This last feature is a very powerful stick, and you can considerably hurt yourself with it. Signed-off-by: Luke Kanies <luke@puppetlabs.com>
* Removing Resource::Reference classesLuke Kanies2010-02-171-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit is hopefully less messy than it first appears, but it's certainly cross-cutting. The reason for all of this is that we previously only looked up builtin resource types from outside the parser, but now that the defined resource types are available globally via environments, we can push that lookup code to Resource. Once we do that, however, we have to have environment and namespace information in every resource. Here I remove the Resource::Reference classes (except the AST class), and use Resource instances instead. I did this because the shared code between the two classes got incredibly complicated, such that they should have had a hierarchical relationship disallowed by their constants. This complexity convinced me just to get rid of References entirely. I also make Puppet::Parser::Resource a subclass of Puppet::Resource. There are still broken tests in test/, but this was a big enough commit I wanted to get it in. Signed-off-by: Luke Kanies <luke@reductivelabs.com>
* Renaming Parser::ResourceType to Resource::TypeLuke Kanies2010-02-171-3/+3
| | | | | | | | | | Basically, these classes (ResourceType and ResourceTypeCollection) don't really belong in Parser, so I'm moving them to the Resource namespace. This will be where anything RAL-related goes from now on, and as we migrate functionality out of Puppet::Type, it should go here. Signed-off-by: Luke Kanies <luke@reductivelabs.com>
* Removing Interpreter classLuke Kanies2010-02-171-0/+7
| | | | | | | It's no longer necessary, given the new ResourceTypeCollection class. Signed-off-by: Luke Kanies <luke@reductivelabs.com>
* All non-transient parser references are goneLuke Kanies2010-02-171-14/+12
| | | | | | | | | We now use references to the ResourceTypeCollection instances through the environment, which is much cleaner. The next step is to remove the Interpreter class. Signed-off-by: Luke Kanies <luke@reductivelabs.com>
* Move scope parenting & class_scope from Compiler to ScopeMarkus Roberts2010-02-171-46/+6
| | | | | | | | | | | | | | | | This refactor fixes about a quarter of the test failures on master and (I hope) will simplify some of the integration issues on the testing branch. It is my best guess at The Right Thing To Do (or at least a step in that direction) but I could be persuaded otherwise. The basic idea is to take responsibility for maintaining scope hierarchy and class_name -> class_scope mapping out of the compiler class and put it in the scope class where it arguably belongs. To maintain the semantics, class scopes are all tracked by the "top level" scope, though this could be relaxed if the nesting semantics were ever needed. If this winds up being the right thing to do, related routines (e.g. newscope) should be sorted out as well.
* Fixing #2596 - Node, Class, Definition are not ASTLuke Kanies2009-12-091-4/+4
| | | | | | | | | | | | | | | | | This commit extracts these three classes into a single ResourceType class in the Parser heirarchy, now completely independent of the AST heirarchy. Most of the other changes are just changing the interface to the new class, which is greatly simplified over the previous classes. This opens up the possibility of drastically simplifying a lot of this other code, too -- in particular, replacing the reference to the parser with a reference to the (soon to be renamed) LoadedCode class. Signed-off-by: Luke Kanies <luke@madstop.com>
* Fixing #2735 - node classes are immed. added to classlistLuke Kanies2009-10-181-0/+3
| | | | | | | | | This commit adds any external node classes to the classlist at compiler initialization, so that at least those classes will be isolated from any ordering issues encountered when testing the contents of the class list during compilation. Signed-off-by: Luke Kanies <luke@madstop.com>
* Adding version information to the catalog for compatLuke Kanies2009-09-221-0/+4
| | | | | | | We need to be able to do compatibility testing, and this allows us to do so. Signed-off-by: Luke Kanies <luke@madstop.com>
* Fixing #2423 - no more strange dependency cyclesLuke Kanies2009-07-251-1/+5
| | | | | | | | | | | | | | | We were getting strange dependency cycles because our class structure mirrored our scope structure. We can't change the scope structure without switching from a dynamically scoped language to a lexically scoped language, which is too big of a change to make right now. Instead, I'm changing the resource graph so that all classes default to just having an edge to the 'main' graph. This will be a behaviour change for many, in that you were getting automatic dependencies from this old behaviour, but it will bring consistency. Signed-off-by: Luke Kanies <luke@madstop.com>
* Switching to LoadedCode from ASTSetLuke Kanies2009-07-051-5/+5
| | | | | | | | I also took the opportunity to clean up and simplify the interface to the parts of the parser that interact with this. Mostly it was method renames. Signed-off-by: Luke Kanies <luke@madstop.com>
* Switching to Indirected ActiveRecordLuke Kanies2009-04-221-37/+0
| | | | | | | | | | | This is mostly a configuration change, with some code getting removed. Also adding an extra require in Format; Puppet::Provider requires Puppet::Provider::Confiner, so the constant lookup is weird. Signed-off-by: Luke Kanies <luke@madstop.com>
* Fix #1933 - Inconsistent resource evaluation order in subsequent evaluation runsBrice Figureau2009-02-141-9/+10
| | | | | | | | | | | | | While evaluating the AST, catalog vertices are not always ordered the same way on different run, leading to some tags (which should have been applied in evaluation order) to not be associated with some underlying resources. This changeset change all accesses to resources inside the compiler to always use an ordered (in evaluation order) list of added resources. Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com>
* Renaming Puppet::Node::Catalog to Puppet::Resource::CatalogLuke Kanies2008-12-181-2/+2
| | | | Signed-off-by: Luke Kanies <luke@madstop.com>
* Fixing an error message to be more clearLuke Kanies2008-05-011-1/+1
|
* Always duplicating resource defaults in the parser, so thatLuke Kanies2008-03-061-1/+0
| | | | | | stacked metaparameter values do not result in all resources that receive a given default also getting those stacked values.
* Fixing #1092 by no longer using the resource reference toLuke Kanies2008-02-281-3/+2
| | | | | | look resources up, which means there's no concern about not finding the resource, which is where the nil was coming from. We now just iterate over the vertices.
* Merge commit 'bartv/pending/fix-997' into 0.24.xLuke Kanies2008-02-121-2/+6
|
* Moving the ast node tests to rspec (which I could haveLuke Kanies2008-02-121-2/+3
| | | | | | | *sworn* I did this weekend). In the process, I fixed a couple of bugs related to differentiating between nodes and classes, and then cleaned up quite a few error messages.
* Removing the last remaining vestiges of GRATR --Luke Kanies2008-02-111-3/+3
| | | | removing the bangs from 'add_vertex!' and 'add_edge!'.
* Changing the name of the Compile class to Compiler,Luke Kanies2008-02-111-0/+467
since it's stupid to have a class named after a verb.