From 46fdaaba6b20ce548f2a5adc51c5954c55fc402c Mon Sep 17 00:00:00 2001
From: Dean Troyer <dtroyer@gmail.com>
Date: Tue, 20 Oct 2015 15:44:38 -0500
Subject: [PATCH] Add Command Options guideline doc

Add a developer guideline for command options to define the options
used across multiple commands and make them behave consistently.

Change-Id: I1dbbafe8061e10b271cd55cac056731508c52204
---
 doc/source/command-options.rst | 135 +++++++++++++++++++++++++++++++++
 doc/source/index.rst           |   1 +
 2 files changed, 136 insertions(+)
 create mode 100644 doc/source/command-options.rst

diff --git a/doc/source/command-options.rst b/doc/source/command-options.rst
new file mode 100644
index 0000000000..edafb15322
--- /dev/null
+++ b/doc/source/command-options.rst
@@ -0,0 +1,135 @@
+===============
+Command Options
+===============
+
+OpenStackClient commands all have a set of zero or more options unique to
+the command, however there are of course ways in which these options are
+common and consistent across all of the commands that include them.
+
+These are the set of guidelines for OSC developers that help keep the
+interface and commands consistent.
+
+In some cases (like the boolean variables below) we use the same pattern
+for defining and using options in all situations.  The alternative of only
+using it when necessary leads to errors when copy-n-paste is used for a
+new command without understanding why or why not that instance is correct.
+
+Boolean Options
+===============
+
+Boolean options for any command that sets a resource state, such as 'enabled'
+or 'public', shall always have both positive and negative options defined.
+The names of those options shall either be a naturally occuring pair of
+words (in English) or a positive option and a negative option with `no-`
+prepended (such as in the traditional GNU option usage) like `--share` and
+`--no-share`.
+
+In order to handle those APIs that behave differently when a field is set to
+`None` and when the field is not present in a passed argument list or dict,
+each of the boolean options shall set its own variable to `True` as part of
+a mutiually exclusive group, rather than the more common configuration of setting a
+single destination variable `True` or `False` directly.  This allows us to
+detect the situation when neither option is present (both variables will be
+`False`) and act accordingly for those APIs where this matters.
+
+This also requires that each of the boolean values be tested in the
+`take_action()` method to correctly set (or not) the underlying API field
+values.
+
+.. option:: --enable
+
+    Enable <resource> (default)
+
+.. option:: --disable
+
+    Disable <resource>
+
+Implementation
+~~~~~~~~~~~~~~
+
+The parser declaration should look like this::
+
+.. code-block: python
+
+        enable_group = parser.add_mutually_exclusive_group()
+        enable_group.add_argument(
+            '--enable',
+            action='store_true',
+            help=_('Enable <resource> (default)'),
+        )
+        enable_group.add_argument(
+            '--disable',
+            action='store_true',
+            help=_('Disable <resource>'),
+        )
+
+An example handler in `take_action()`::
+
+        # This leaves 'enabled' undefined if neither option is present
+        if parsed_args.enable:
+            kwargs['enabled'] = True
+        if parsed_args.disable:
+            kwargs['enabled'] = False
+
+List Command Options
+====================
+
+Additional Fields
+-----------------
+
+Most list commands only return a subset of the available fields by default.
+Additional fields are available with the `--long` option.  All list
+commands should allow `--long` even if they return all fields by default.
+
+.. option:: --long
+
+    List additional fields in output
+
+Implementation
+~~~~~~~~~~~~~~
+
+The parser declaration should look like this::
+
+.. code-block: python
+
+        parser.add_argument(
+            '--long',
+            action='store_true',
+            default=False,
+            help='List additional fields in output',
+        )
+
+Pagination
+----------
+
+There are many ways to do pagination, some OpenStack APIs support it, some don't.
+OpenStackClient attempts to define a single common way to specify pagination on
+the command line.
+
+.. option:: --marker <marker>
+
+    Anchor for paging
+
+.. option:: --limit <limit>
+
+    Limit number of <resource> returned (*integer*)
+
+Implementation
+~~~~~~~~~~~~~~
+
+The parser declaration should look like this::
+
+.. code-block: python
+
+        parser.add_argument(
+            "--marker",
+            metavar="<marker>",
+            help="Anchor for paging",
+        )
+
+        parser.add_argument(
+            "--limit",
+            metavar="<limit>",
+            type=int,
+            help="Limit the number of <resource> returned",
+        )
diff --git a/doc/source/index.rst b/doc/source/index.rst
index c90b8e5296..6b7d63f36e 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -37,6 +37,7 @@ Developer Documentation
    :maxdepth: 1
 
    developing
+   command-options
 
 Project Goals
 -------------