This document describes the conventions of neutron CLI options.
--ip-version
--ip_version
*-create
command. If all options
are optional, we typically use name
field as a required option.name
or other reasonable field.foo_id
, the corresponding option
should be --foo
instead of --foo-id
.name
to specify a resource.nargs='?'
without a special reason.nargs='?'
option for python argparse is
bit tricky and may lead to unexpected option parsing different
from the help message. The detail is described in the
Background section below.Use the form of --option-name {True|False}
.
common.utils.add_boolean_argument
in an
implementation. It allows true
/false
in addition to 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:
--host-route destination=CIDR,nexthop=IP_ADDR
for a subnet--fixed-ip subnet_id=SUBNET,ip_address=IP_ADDR
for a port.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.
--foo True
, --bar=False
--bars list=true val1 val2
, --bars val1 val2
--foo type=dict key1=va1,key2=val2
--bars list=true type=dict key1=val1,key2=val2 key3=val3,key4=val4
action=clear
For normal options with value, there are four patterns to specify an option as extra arguments.
--admin-state-up True
(a space between option name and value)--admin-state-up=True
(= between option name and value)--admin_state_up True
(underscore is used as delimiter)--admin_state_up=True
(underscore is used as delimiter)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:
neutron *-create
without a required argument, we will have a
brief help message without detail option help. It is convenient.neutron *-create
.
Requiring at least one parameter is a good balance.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.
--enable-foo
/--disable-foo
or similar patterns (including
--admin-state-down
) is not suggested because we need two exclusive
options for one attribute in REST API. It is meaningless.--shared
or --admin-state-down
options for
net-create. This form only works for *-create
and does not work for
*-update
. It leads to having different options for *-create
and
*-update
.--enable-dhcp
(without value) also has a problem when
considering the compatibility with extra argument. We can specify
-enable-dhcp True/False
or --enable-dhcp=True/False
in the extra
argument mechanism. If we introduce --enable-dhcp
(without value),
the form of -enable-dhcp True/False
cannot be used now.
This is another reason we don’t use a flag style option for a boolean parameter.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.
Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.