This document describes the conventions of neutron CLI options.
Use the form of --option-name {True|False}.
Some API attributes take a dictionary.
--foo key1=val1,key2=val2 is usually used.
This means {"key1": "val1", "key2": "val2"} is passed in the API layer.
Examples:
Some attributes take a list.
In this case, we usually use:
For Example, port-create has --security-group option. --security-group SG1 --security-group SG2 generates {"security_groups: ["SG1", "SG2"]} in the API layer.
This convention applies to a case of a list of dict. --allocation-pool and --host-route for a subnet are examples.
extra arguments supports various types of option specifications. At least the following patterns needs to be considered when defining a new option. For more detail, see Extra arguments for create/update operation.
For normal options with value, there are four patterns to specify an option as extra arguments.
There are a lot of opinions on which form of options are better or not. This section tries to capture the reason of the current choice.
As a convention, neutron CLI requires one required argument.
If all options are optional in the API level and we have name field, we usually use name as a required parameter. Requiring at least one argument has the following benefits:
Even though we can change this convention to allow to create a resource without name field, it will bring confusions to existing users.
There may be opinion that it is inconsistent with API level requirement or Horizon behavior, but even if neutron CLI requires name field there is no bad impact on regular users. Considering possible confusion if we change it, it looks better to keep it as-is.
The behavior of nargs='?' option for python argparse is bit tricky. When we use nargs='?' and if the order of command-line options is changed then the command-line parser may fail to parse the arguments correctly. Two examples of such failures are provided below.
Example 1: This example shows how the actual behavior can differ from the provided help message. In the below block, help message at [5] says --bb CC is a valid format but the argument parsing for the same format fails at [7].
In [1]: import argparse
In [2]: parser = argparse.ArgumentParser()
In [3]: parser.add_argument('--bb', nargs='?')
In [4]: parser.add_argument('cc')
In [5]: parser.print_help()
usage: ipython [-h] [--bb [BB]] cc
positional arguments:
cc
optional arguments:
-h, --help show this help message and exit
--bb [BB]
In [6]: parser.parse_args('--bb 1 X'.split())
Out[6]: Namespace(bb='1', cc='X')
In [7]: parser.parse_args('--bb X'.split())
usage: ipython [-h] [--bb [BB]] cc
ipython: error: too few arguments
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
Example 2: This example shows how fragile nargs='?' can be when user specifies options in different order from the help message.
In [1]: import argparse
In [2]: parser = argparse.ArgumentParser()
In [3]: parser.add_argument('--a', help='option a')
In [4]: parser.add_argument('--b', help='option b')
In [5]: parser.add_argument('x', help='positional arg X')
In [6]: parser.add_argument('y', nargs='?', help='positional arg Y')
In [7]: parser.print_help()
usage: ipython [-h] [--a A] [--b B] x [y]
positional arguments:
x positional arg X
y positional arg Y
optional arguments:
-h, --help show this help message and exit
--a A option a
--b B option b
In [8]: parser.parse_args('--a 1 --b 2 X Y'.split())
Out[8]: Namespace(a='1', b='2', x='X', y='Y')
In [9]: parser.parse_args('X Y --a 1 --b 2'.split())
Out[9]: Namespace(a='1', b='2', x='X', y='Y')
In [10]: parser.parse_args('X --a 1 --b 2 Y'.split())
usage: ipython [-h] [--a A] [--b B] x [y]
ipython: error: unrecognized arguments: Y
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
To exit: use 'exit', 'quit', or Ctrl-D.
To exit: use 'exit', 'quit', or Ctrl-D.
Note: Most CLI users don’t care about the order of the command-line options. Hence, such fragile behavior should be avoided.