Skip to content

Commit

Permalink
Merge pull request #7242 from DavidS/pup-8766-device-load-path
Browse files Browse the repository at this point in the history
(PUP-8766) device $LOAD_PATH and environment handling
  • Loading branch information
DavidS authored Dec 7, 2018
2 parents 6d084ee + e1a810b commit f170937
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 33 deletions.
74 changes: 45 additions & 29 deletions lib/puppet/application/device.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'puppet/application'
require 'puppet/configurer'
require 'puppet/util/network_device'

class Puppet::Application::Device < Puppet::Application
Expand Down Expand Up @@ -53,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
Expand Down Expand Up @@ -93,10 +98,11 @@ def help
USAGE
-----
puppet device [-d|--debug] [--detailed-exitcodes] [--deviceconfig <file>]
[-h|--help] [-l|--logdest syslog|<file>|console]
[-v|--verbose] [-w|--waitforcert <seconds>] [-f|--facts]
[-a|--apply <file>] [-r|--resource <type> [name]]
puppet device [-h|--help] [-v|--verbose] [-d|--debug]
[-l|--logdest syslog|<file>|console] [--detailed-exitcodes]
[--deviceconfig <file>] [-w|--waitforcert <seconds>]
[--libdir <directory>]
[-a|--apply <file>] [-f|--facts] [-r|--resource <type> [name]]
[-t|--target <device>] [--user=<user>] [-V|--version]
Expand Down Expand Up @@ -135,9 +141,25 @@ def help
long argument. For example, 'server' is a valid configuration parameter, so
you can specify '--server <servername>' 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
Expand All @@ -149,18 +171,16 @@ def help
Path to the device config file for puppet device.
Default: $confdir/device.conf
* --help:
Print this help message
* --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.
* --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.
* --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.
Expand All @@ -183,16 +203,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
-------
Expand All @@ -205,7 +215,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
Expand All @@ -222,11 +232,12 @@ 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]

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'
Expand All @@ -251,9 +262,13 @@ def main

# override local $vardir and $certname
Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name)
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] || options[:libdir]
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)
Expand Down Expand Up @@ -309,13 +324,14 @@ 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)
# 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
Expand Down
5 changes: 2 additions & 3 deletions lib/puppet/util/command_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion spec/unit/application/device_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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({})
Expand Down Expand Up @@ -504,7 +505,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
Expand Down

0 comments on commit f170937

Please sign in to comment.