[PUP-4429] Puppet command line tools accept partial matches for flags without altering behavior Created: 2015/04/16  Updated: 2019/04/04

Status: Accepted
Project: Puppet
Component/s: None
Affects Version/s: PUP 3.7.5, PUP 4.0.0
Fix Version/s: PUP 5.y

Type: Bug Priority: Normal
Reporter: Charlie Sharpsteen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: redmine
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Template:
Team: Coremunity

 Description   

The Puppet command line tools will accept partial matches for flags, but do not use the values provided. This causes unexpected behavior when a command accepts a flag or type but doesn't actually act upon it.

Reproduction Case

Install Puppet 3.7.x or 4.0.x.

Execute config print commands with flags that affect settings, such as puppet agent --no-daemonize --configprint daemonize with various truncations of the --no-daemonize flag.

Outcome

Partial matches are accepted, but don't alter the setting value:

puppet agent --no-daemon --configprint daemonize
true
 
puppet agent --no-daemoniz --configprint daemonize
true
 
# Correct behavior when flag is fully specified.
puppet agent --no-daemonize --configprint daemonize
false

Expected Outcome

The Puppet command line interface should treat partial flags the same way as missing flags and throw an 'invalid option' error:

puppet agent --no-daemon
Error: Could not parse application options: invalid option: --no-daemon



 Comments   
Comment by Charlie Sharpsteen [ 2015/04/16 ]

Updated notes from Redmine ticket #19306:


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-daemon to 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.
Comment by Kylo Ginsberg [ 2015/04/16 ]

We should consider this ticket in any plans to work on the puppet CLI.

Generated at Thu Nov 14 00:58:23 PST 2019 using JIRA 7.7.1#77002-sha1:e75ca93d5574d9409c0630b81c894d9065296414.