summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorDaniel Pittman <daniel@puppetlabs.com>2011-06-01 17:51:25 -0700
committerDaniel Pittman <daniel@puppetlabs.com>2011-06-01 17:51:25 -0700
commitb70f32a45a5dd5777c341e43816d54c37707cf27 (patch)
tree4dee5818c84b80abce613b2dfa9ff5e045aa5110 /lib/puppet
parent80c197807faaaf839057c212e69ad0915b39bfe4 (diff)
downloadpuppet-b70f32a45a5dd5777c341e43816d54c37707cf27.tar.gz
puppet-b70f32a45a5dd5777c341e43816d54c37707cf27.tar.xz
puppet-b70f32a45a5dd5777c341e43816d54c37707cf27.zip
(#7746) Fix bootstrap issues from #7717 fix.
So, turns out the fix in #7717 introduced a failure when starting the Puppet master on some versions of Ruby. Weird stuff. I figured it out, eventually. You see, the process of bootstrapping Puppet is ... complex. This file, like many of our early initialization files, has an incestuous relationship between the order of files loaded, code executed at load time, and code executed in other files at runtime. When we construct this object we have not yet actually loaded the global puppet object, so we can't use any methods in it. That includes all the logging stuff, which is used by the deprecation warning subsystem. On the other hand, we can't just load the logging system, because that depends on the top level Puppet module being bootstrapped. It doesn't actually load the stuff it uses, though, for hysterical raisins. Finally, we can't actually just load the top level Puppet module. This one is precious: it turns out that some of the code loaded in the top level Puppet module has a dependency on the run mode values. Run mode is set correctly *only* when the application is loaded, and if it is wrong when the top level code is brought in we end up with the wrong settings scattered through some of the defaults. Which means that we have a dependency cycle that runs: 1. The binary creates an instance of P::U::CL. 2. That identifies the application to load. 3. It does, then instantiates the application. 4. That sets the run-mode. 5. That then loads the top level Puppet module. 6. Finally, we get to where we can use the top level stuff So, essentially, we see a dependency between runtime code in this file, run-time code in the application, and load-time code in the top level module. Which leads me to our current horrible hack: we stash away the message we wanted to log about deprecation, then send it to our logging system once we have done enough bootstrapping that it will, y'know, actually work. I would have liked to fix this, but that is going to be a whole pile of work digging through and decrufting all the global state from the local state, and working out what depends on what else in the product. Oh, and we use a global because we have *two* instances of a P::U::CL object during the startup sequence. I don't know why. Reviewed-By: Nigel Kersten <nigel@puppetlabs.com> Reviewed-By: Nick Lewis <nick@puppetlabs.com> Reviewed-By: Jacob Helwig <jacob@puppetlabs.com>
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/util/command_line.rb71
1 files changed, 62 insertions, 9 deletions
diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb
index 372aa5122..244e2c2c9 100644
--- a/lib/puppet/util/command_line.rb
+++ b/lib/puppet/util/command_line.rb
@@ -59,6 +59,13 @@ module Puppet
require_application subcommand_name
app = Puppet::Application.find(subcommand_name).new(self)
Puppet::Plugins.on_application_initialization(:appliation_object => self)
+
+ # See the note in 'warn_later' down below. --daniel 2011-06-01
+ if $delayed_deprecation_warning_for_p_u_cl.is_a? String then
+ Puppet.deprecation_warning($delayed_deprecation_warning_for_p_u_cl)
+ $delayed_deprecation_warning_for_p_u_cl = true
+ end
+
app.run
elsif execute_external_subcommand then
# Logically, we shouldn't get here, but we do, so whatever. We just
@@ -98,7 +105,7 @@ module Puppet
[nil, argv] # ttys get usage info
else
# Killed for 2.7.0 --daniel 2011-06-01
- Puppet.deprecation_warning <<EOM
+ warn_later <<EOM
Implicit invocation of 'puppet apply' by redirection into 'puppet' is deprecated,
and will be removed in the 2.8 series. Please invoke 'puppet apply' directly
in the future.
@@ -110,7 +117,7 @@ EOM
[nil, argv]
when /^-|\.pp$|\.rb$/ then
# Killed for 2.7.0 --daniel 2011-06-01
- Puppet.deprecation_warning <<EOM
+ warn_later <<EOM
Implicit invocation of 'puppet apply' by passing files (or flags) directly
to 'puppet' is deprecated, and will be removed in the 2.8 series. Please
invoke 'puppet apply' directly in the future.
@@ -124,13 +131,59 @@ EOM
end
end
+ # So, this is more than a little bit of a horror. You see, the process
+ # of bootstrapping Puppet is ... complex. This file, like many of our
+ # early initialization files, has an incestuous relationship between the
+ # order of files loaded, code executed at load time, and code executed
+ # in other files at runtime.
+ #
+ # When we construct this object we have not yet actually loaded the
+ # global puppet object, so we can't use any methods in it. That
+ # includes all the logging stuff, which is used by the deprecation
+ # warning subsystem.
+ #
+ # On the other hand, we can't just load the logging system, because that
+ # depends on the top level Puppet module being bootstrapped. It doesn't
+ # actually load the stuff it uses, though, for hysterical raisins.
+ #
+ # Finally, we can't actually just load the top level Puppet module.
+ # This one is precious: it turns out that some of the code loaded in the
+ # top level Puppet module has a dependency on the run mode values.
+ #
+ # Run mode is set correctly *only* when the application is loaded, and
+ # if it is wrong when the top level code is brought in we end up with
+ # the wrong settings scattered through some of the defaults.
+ #
+ # Which means that we have a dependency cycle that runs:
+ # 1. The binary creates an instance of P::U::CL.
+ # 2. That identifies the application to load.
+ # 3. It does, then instantiates the application.
+ # 4. That sets the run-mode.
+ # 5. That then loads the top level Puppet module.
+ # 6. Finally, we get to where we can use the top level stuff
+ #
+ # So, essentially, we see a dependency between runtime code in this
+ # file, run-time code in the application, and load-time code in the top
+ # level module.
+ #
+ # Which leads me to our current horrible hack: we stash away the message
+ # we wanted to log about deprecation, then send it to our logging system
+ # once we have done enough bootstrapping that it will, y'know, actually
+ # work.
+ #
+ # I would have liked to fix this, but that is going to be a whole pile
+ # of work digging through and decrufting all the global state from the
+ # local state, and working out what depends on what else in the product.
+ #
+ # Oh, and we use a global because we have *two* instances of a P::U::CL
+ # object during the startup sequence. I don't know why.
+ #
+ # Maybe, one day, when I am not behind a deadline to ship code.
+ # --daniel 2011-06-01
+ def warn_later(text)
+ return if $delayed_deprecation_warning_for_p_u_cl
+ $delayed_deprecation_warning_for_p_u_cl = text
+ end
end
end
end
-
-# REVISIT: Without this, we can't use the full Puppet suite inside the code,
-# but we can't include it before we get this far through defining things as
-# this code is the product of incestuous union with the global code; global
-# code at load scope depends on methods we define, while we only depend on
-# them at runtime scope. --daniel 2011-06-01
-require 'puppet'