The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com
https://tickets.puppetlabs.com. See the following page for information on filing tickets with JIRA:
Puppet option parser accepts partial matches but doesn't use them to alter configuration values
|Affected Puppet version:||3.0.0||Branch:|
Ticket tracking is now hosted in JIRA: https://tickets.puppetlabs.com
This popped up during investigation of #19153.
When a Puppet command such as
agent encounters an unknown option, it throws a warning:
# puppet agent --foo Error: Could not parse application options: invalid option: --foo
Similarly, when it encounters a known option, it will alter a config value:
# puppet agent --configprint daemonize true # puppet agent --no-daemonize --configprint daemonize false
However, the parser will also accept partial matches:
# puppet agent --no-daemoniz --configprint daemonize true # puppet agent --no-daemon --configprint daemonize true # puppet agent --no-da --configprint daemonize true Edge Cases: # puppet agent --no-daemonizer --configprint daemonize Error: Could not parse application options: invalid option: --no-daemonizer # puppet agent --no-d --configprint daemonize Error: Could not parse application options: ambiguous option: --no-d
The problems with partial matching is that the flags don’t alter configuration values and no warning or error is emitted to alert users that their input is incorrect or that their intentions are not being honored.
#1 Updated by Charlie Sharpsteen almost 3 years ago
Drilled the problem down a bit. A command line invocation, such as
puppet agent --no-daemon, goes through two rounds of option parsing. This first round occurs in /util/command_line.rb and ends up triggering a block of code in settings.rb:
def parse_global_options(args) # Create an option parser option_parser = PuppetOptionParser.new option_parser.ignore_invalid_options = true ...
The important things to note is that this first round uses
PuppetOptionParser which is a modified Trollop parser and that ignore_invalid_options is set to true because at this point Puppet doesn’t know which subcommand is being executed. Because of this, the unknown
--no-daemon flag slips through the first round of parsing without raising an error.
The second round of parsing occurs within the Application class in the parse_options method. This round of parsing uses the OptionParser class from the optparse module in the Ruby standard library. The OptionParser class is capable of autocorrecting
--no-daemonize and in fact always performs this correction—-there is no way to disable it. The command line arguments that match Puppet’s global settings are passed to the handlearg function… which ignores them completely.
There are a few issues here:
We process command line arguments with two different parsing classes. We should be using one class if possible to reduce differences in behavior.
The handlearg function never uses the information it is passed to adjust Puppet settings.
The OptionParser destroys the original flag that was passed by the user when performing partial matching, so there is no way for handlearg to raise a note or warning about the use of a partial match.
#2 Updated by Charlie Sharpsteen almost 3 years ago
- Status changed from Unreviewed to Accepted
- Affected Puppet version changed from 3.1.0 to 3.0.0
Also appears that partial matching works in the 2.7.x series but not 3.x. Bisected the change in behavior down to cb3ce74. Appears this is where the split between OptionParser and Trollop was introduced.