On Mon, Dec 1, 2014 at 11:44 AM, Trevor Vaughan <tvaug...@onyxpoint.com> wrote:
> Well that makes a ridiculous amount of sense. > > Thanks for posting, I'll check it out tomorrow. > > Trevor > > On Mon, Dec 1, 2014 at 4:20 AM, Gavin Williams <fatmc...@gmail.com> wrote: > >> The code I've added to work-around the Puppet issue is here[1]. >> > >> HTH. >> >> Gav >> >> [1]https://gist.github.com/fatmcgav/aa7295798502d660c6a3 >> > Thanks Gavin for posting that, and for the ticket and PR. I think your "work-around" is really the right thing to be doing. Puppet's autoloader has a fatal flaw that causes a host of issues where code cannot be loaded. See the linked issues in https://projects.puppetlabs.com/issues/7316 A good example is the case where you have a module defining a new type in lib/puppet/type/foo.rb: require 'puppet/type/bar' Puppet::Type.newtype(:foo) do end And the `foo` type requires helper code `bar` from within the same (or different) module. The problem with puppet's autoloader is that it only participates in the loading of `foo`, but is "out of the loop" when `foo` requires `bar`. As a result we have the autoloader loading `foo`, but Ruby loading `bar`. What could possibly go wrong? 1. Well, the autoloader searches the current environment's modulepath to load `foo`, but Ruby only knows about $LOAD_PATH. As a result, modules often fail to load their helper code[1], or the module works around it by using the absolute path to the helper code[2], or it tries to rescue LoadError and do something "smart"[3]. This is a terrible pattern. 2. The autoloader uses `Kernel.load` to load `foo`[4], but Ruby requires `bar`. If the class has already been required, the former will reload the class, whereas the latter will not. In long running processes, e.g. master, it is possible for the autoloader to reload a new version of a function, but never reload the helper code that the function relies on[5]. So you have a new version of `foo` running with an old version of `bar`, leading to nearly impossible to debug scenarios, e.g. NoMethodErrors that magically disappear when you restart the master[6]. 3. Historically, the Puppet[:libdir] setting has allowed multiple directories to be added to the autoloader's search path, but it has no effect on Ruby's $LOAD_PATH. While this "works" in some cases, e.g when using puppet as a library or rspec tests[7], it would fail hard if you ever tried to run `puppet apply` with that setting[8]. 4. To solve https://projects.puppetlabs.com/issues/7316, Andy and I took the approach that puppet (the application) should be responsible for setting up the ruby $LOAD_PATH[9], and puppet (the library) should just use the current $LOAD_PATH. I think we should do something similar for the rspec-puppet case, where the thing that runs the tests is responsible for updating the $LOAD_PATH to include module specific paths. But this raises a few questions: Does this belong in rspec-puppet, puppetlabs_spec_helper, or puppet's own testing methods (lib/puppet/test/helper.rb)? What environment/modulepath should be used, especially once legacy environment support is removed[10]? Josh [1] https://tickets.puppetlabs.com/browse/PUP-3336 [2] https://github.com/puppetlabs/puppetlabs-mysql/blob/master/lib/puppet/provider/mysql_database/mysql.rb#L1 [3] https://github.com/puppetlabs/puppetlabs-registry/blob/master/lib/puppet/provider/registry_key/registry.rb#L2-L12 [4] https://github.com/puppetlabs/puppet/blob/3.7.3/lib/puppet/util/autoload.rb#L62 [5] https://tickets.puppetlabs.com/browse/PUP-1033 [6] https://tickets.puppetlabs.com/browse/PUP-2380 [7] https://github.com/rodjek/rspec-puppet/blob/master/lib/rspec-puppet/support.rb#L140 [8] https://tickets.puppetlabs.com/browse/PUP-3336?focusedCommentId=114681&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-114681 [9] https://github.com/puppetlabs/puppet/blob/3.7.3/lib/puppet/util/command_line.rb#L135-L141 [10] https://tickets.puppetlabs.com/browse/PUP-3268 -- Josh Cooper Developer, Puppet Labs *Join us at **PuppetConf 2015, October 5-9 in Portland, OR - * http://2015.puppetconf.com. *Register early to save 40%!* -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CA%2Bu97u%3DaUST95KmRF-E4wx43q3wMfsK8SNvXTEY4U9aHsYe_EA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.