From 606d4a3c8c3743ad1618ad0265dea1bd5067b15c Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 7 Dec 2018 08:56:02 +0000 Subject: [PATCH 1/5] (maint) group options in help text This change groups related options in the help text to improve legibility. --- lib/puppet/application/device.rb | 56 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 5e7a5cd473a..dd0b479e414 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -93,10 +93,10 @@ def help USAGE ----- - puppet device [-d|--debug] [--detailed-exitcodes] [--deviceconfig ] - [-h|--help] [-l|--logdest syslog||console] - [-v|--verbose] [-w|--waitforcert ] [-f|--facts] - [-a|--apply ] [-r|--resource [name]] + puppet device [-h|--help] [-v|--verbose] [-d|--debug] + [-l|--logdest syslog||console] [--detailed-exitcodes] + [--deviceconfig ] [-w|--waitforcert ] + [-a|--apply ] [-f|--facts] [-r|--resource [name]] [-t|--target ] [--user=] [-V|--version] @@ -135,9 +135,25 @@ def help long argument. For example, 'server' is a valid configuration parameter, so you can specify '--server ' as an argument. -* --debug: +* --help, -h: + Print this help message + +* --verbose, -v: + Turn on verbose reporting. + +* --debug, -d: Enable full debugging. +* --logdest, -l: + Where to send log messages. Choose between 'syslog' (the POSIX syslog + service), 'console', or the path to a log file. If debugging or verbosity is + enabled, this defaults to 'console'. Otherwise, it defaults to 'syslog'. + + A path ending with '.json' will receive structured output in JSON format. The + log file will not have an ending ']' automatically written to it due to the + appending nature of logging. It must be appended manually to make the content + valid JSON. + * --detailed-exitcodes: Provide transaction information via exit codes. If this is enabled, an exit code of '1' means at least one device had a compile failure, an exit code of @@ -149,18 +165,12 @@ def help Path to the device config file for puppet device. Default: $confdir/device.conf -* --help: - Print this help message - -* --logdest: - Where to send log messages. Choose between 'syslog' (the POSIX syslog - service), 'console', or the path to a log file. If debugging or verbosity is - enabled, this defaults to 'console'. Otherwise, it defaults to 'syslog'. - - A path ending with '.json' will receive structured output in JSON format. The - log file will not have an ending ']' automatically written to it due to the - appending nature of logging. It must be appended manually to make the content - valid JSON. +* --waitforcert, -w: + This option only matters for targets that do not yet have certificates + and it is enabled by default, with a value of 120 (seconds). This causes + +puppet device+ to poll the server every 2 minutes and ask it to sign a + certificate request. This is useful for the initial setup of a target. + You can turn off waiting for certificates by specifying a time of 0. * --apply: Apply a manifest against a remote target. Target must be specified. @@ -183,16 +193,6 @@ def help * --user: The user to run as. -* --verbose: - Turn on verbose reporting. - -* --waitforcert: - This option only matters for daemons that do not yet have certificates - and it is enabled by default, with a value of 120 (seconds). This causes - +puppet agent+ to connect to the server every 2 minutes and ask it to sign a - certificate request. This is useful for the initial setup of a puppet - client. You can turn off waiting for certificates by specifying a time of 0. - EXAMPLE ------- @@ -205,7 +205,7 @@ def help COPYRIGHT --------- -Copyright (c) 2011 Puppet Inc., LLC +Copyright (c) 2011-2018 Puppet Inc., LLC Licensed under the Apache 2.0 License HELP end From 823a6c78fceda7498c875af3a92d1b02e6f5cc35 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 16 Nov 2018 14:59:17 +0000 Subject: [PATCH 2/5] (PUP-9318) fix $LOAD_PATH handling in `device` Previous to this commit, `puppet device` would use the proxy agent's `:libdir` to load all code, since we changed the `:vardir` setting, but not the `:libdir`. While `Puppet::Settings` has hooks to change the `$LOAD_PATH` when `:libdir` changes, those do not trigger when the change is effected through a interpolation, like in this case. By setting the `:libdir` explicitely the hook is triggered, and the `$LOAD_PATH` gets updated. This commit also removes the `device` subcommand from the CLI's default `$LOAD_PATH` processing. --- lib/puppet/application/device.rb | 3 +++ lib/puppet/util/command_line.rb | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index dd0b479e414..733dce8c8ad 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -222,6 +222,7 @@ def main raise _("missing argument: --target is required when using --apply") if options[:target].nil? raise _("%{file} does not exist, cannot apply") % { file: options[:apply] } unless File.file?(options[:apply]) end + libdir = Puppet[:libdir] vardir = Puppet[:vardir] confdir = Puppet[:confdir] certname = Puppet[:certname] @@ -251,6 +252,7 @@ def main # override local $vardir and $certname Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name) + Puppet[:libdir] = ::File.join(Puppet[:devicedir], device.name, 'lib') Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name) Puppet[:certname] = device.name @@ -316,6 +318,7 @@ def main # If we rescued an error, then we return 1 as the exit code 1 ensure + Puppet[:libdir] = libdir Puppet[:vardir] = vardir Puppet[:confdir] = confdir Puppet[:certname] = certname diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index 8f0e0cf78bd..a6ce0dd55f6 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -106,7 +106,7 @@ def initialize(subcommand_name, command_line) def run # For most applications, we want to be able to load code from the modulepath, # such as apply, describe, resource, and faces. - # For agent, we only want to load pluginsync'ed code from libdir. + # For agent and device, we only want to load pluginsync'ed code from libdir. # For master, we shouldn't ever be loading per-environment code into the master's # ruby process, but that requires fixing (#17210, #12173, #8750). So for now # we try to restrict to only code that can be autoloaded from the node's @@ -116,8 +116,7 @@ def run # have an appropriate application-wide current_environment set. # If we cannot find the configured environment, which may not exist, # we do not attempt to add plugin directories to the load path. - # - if @subcommand_name != 'master' and @subcommand_name != 'agent' + unless ['master', 'agent', 'device'].include? @subcommand_name if configured_environment = Puppet.lookup(:environments).get(Puppet[:environment]) configured_environment.each_plugin_directory do |dir| $LOAD_PATH << dir unless $LOAD_PATH.include?(dir) From 138b5d0e8b52b333481986e8faea8d2bc7118ce4 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 7 Dec 2018 09:53:17 +0000 Subject: [PATCH 3/5] (PUP-8766) Enable early pluginsync for puppet device agent mode When running `puppet device` in agent mode, a pluginsync needs to happen before the device is loaded. For the non-agent modes `--facts`, `--resource`, and `--apply`, doing no pluginsync is useful since they are used in local workflows (like testing), and for a quicker turnaround when exploring devices. --- lib/puppet/application/device.rb | 4 ++++ spec/unit/application/device_spec.rb | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 733dce8c8ad..3b4e9238456 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -1,4 +1,5 @@ require 'puppet/application' +require 'puppet/configurer' require 'puppet/util/network_device' class Puppet::Application::Device < Puppet::Application @@ -256,6 +257,9 @@ def main Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name) Puppet[:certname] = device.name + unless options[:resource] || options[:facts] || options[:apply] + Puppet::Configurer::PluginHandler.new.download_plugins(env) + end # this init the device singleton, so that the facts terminus # and the various network_device provider can use it Puppet::Util::NetworkDevice.init(device) diff --git a/spec/unit/application/device_spec.rb b/spec/unit/application/device_spec.rb index 6077e706cf8..2d56118e894 100644 --- a/spec/unit/application/device_spec.rb +++ b/spec/unit/application/device_spec.rb @@ -504,7 +504,9 @@ expect { @device.main }.to exit_with 1 end - it "should print the device url scheme, host, and port" do + it "should retrieve plugins and print the device url scheme, host, and port" do + Puppet.stubs(:info) + Puppet.expects(:info).with "Retrieving pluginfacts" Puppet.expects(:info).with "starting applying configuration to device1 at ssh://testhost" Puppet.expects(:info).with "starting applying configuration to device2 at https://testhost:443/some/path" expect { @device.main }.to exit_with 1 From 4b76871323c4b720cc4735c5275c50d32bf54e53 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 7 Dec 2018 09:54:08 +0000 Subject: [PATCH 4/5] (PUP-8766) add libdir option for puppet device This allows overriding the per-device libdir to enable local and testing scenarios where pluginsync doesn't make sense. --- lib/puppet/application/device.rb | 15 ++++++++++++--- spec/unit/application/device_spec.rb | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 3b4e9238456..675fbaf5a2b 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -54,6 +54,10 @@ def preinit options[:detailed_exitcodes] = true end + option("--libdir LIBDIR") do |arg| + options[:libdir] = arg + end + option("--apply MANIFEST") do |arg| options[:apply] = arg.to_s end @@ -97,6 +101,7 @@ def help puppet device [-h|--help] [-v|--verbose] [-d|--debug] [-l|--logdest syslog||console] [--detailed-exitcodes] [--deviceconfig ] [-w|--waitforcert ] + [--libdir ] [-a|--apply ] [-f|--facts] [-r|--resource [name]] [-t|--target ] [--user=] [-V|--version] @@ -173,6 +178,10 @@ def help certificate request. This is useful for the initial setup of a target. You can turn off waiting for certificates by specifying a time of 0. +* --libdir: + Override the per-device libdir with a local directory. Specifying a libdir also + disables pluginsync. This is useful for testing. + * --apply: Apply a manifest against a remote target. Target must be specified. @@ -253,11 +262,11 @@ def main # override local $vardir and $certname Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name) - Puppet[:libdir] = ::File.join(Puppet[:devicedir], device.name, 'lib') + Puppet[:libdir] = options[:libdir] || ::File.join(Puppet[:devicedir], device.name, 'lib') Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name) Puppet[:certname] = device.name - unless options[:resource] || options[:facts] || options[:apply] + unless options[:resource] || options[:facts] || options[:apply] || options[:libdir] Puppet::Configurer::PluginHandler.new.download_plugins(env) end # this init the device singleton, so that the facts terminus @@ -315,7 +324,7 @@ def main require 'puppet/configurer' configurer = Puppet::Configurer.new - configurer.run(:network_device => true, :pluginsync => Puppet::Configurer.should_pluginsync?) + configurer.run(:network_device => true, :pluginsync => Puppet::Configurer.should_pluginsync? && !options[:libdir]) end rescue => detail Puppet.log_exception(detail) diff --git a/spec/unit/application/device_spec.rb b/spec/unit/application/device_spec.rb index 2d56118e894..b6a63dd630a 100644 --- a/spec/unit/application/device_spec.rb +++ b/spec/unit/application/device_spec.rb @@ -299,6 +299,7 @@ @device.options.stubs(:[]).with(:facts).returns(false) @device.options.stubs(:[]).with(:resource).returns(false) @device.options.stubs(:[]).with(:to_yaml).returns(false) + @device.options.stubs(:[]).with(:libdir).returns(nil) @device.options.stubs(:[]).with(:client) @device.command_line.stubs(:args).returns([]) Puppet::Util::NetworkDevice::Config.stubs(:devices).returns({}) From e1a810be04645bf4096b5d538ca3b7467ac2d76e Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Fri, 7 Dec 2018 10:56:14 +0000 Subject: [PATCH 5/5] (PUP-9319) Use remote environment for `puppet device` This commit uses a "remote" environment, instead of a full one. This allows the override to work, even if we do not have that environment's codedir available locally. In the case of a full puppet run, the `Configurer` does additional work to update and sync the plugindir vs what the ENC specifies. # Conflicts: # spec/unit/application/device_spec.rb --- lib/puppet/application/device.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 675fbaf5a2b..f9c76e0a323 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -237,7 +237,7 @@ def main confdir = Puppet[:confdir] certname = Puppet[:certname] - env = Puppet.lookup(:environments).get(Puppet[:environment]) + env = Puppet::Node::Environment.remote(Puppet[:environment]) returns = Puppet.override(:current_environment => env, :loaders => Puppet::Pops::Loaders.new(env)) do # find device list require 'puppet/util/network_device/config'