Update CLI Reference generation tool for RST

To migrate CLI Reference from DockBook to RST,
output the documentation in RST format,
with a few work around for RST/Sphinx specific issue.

Change-Id: I32b4cfefa978436061d882f7520bbc92c1645b4e
Implements: blueprint cli-ref-rst
This commit is contained in:
KATO Tomoyuki 2016-01-10 18:09:13 +09:00
parent 4925655305
commit a25b753af2
3 changed files with 221 additions and 232 deletions

View File

@ -89,6 +89,6 @@ git pull
branch=update_client_$project branch=update_client_$project
git branch --list $branch && git branch -D $branch git branch --list $branch && git branch -D $branch
git checkout -b $branch git checkout -b $branch
mv ../output/ch_cli_${project}_commands.xml doc/cli-reference/generated mv ../output/${project}.rst "doc/cli-reference/source"
version=$($project --version 2>&1) version=$($project --version 2>&1)
git commit -a -m "Update CLI reference for python-${project}client ${version##* }" git commit -a -m "Update CLI reference for python-${project}client ${version##* }"

View File

@ -14,6 +14,7 @@
import argparse import argparse
import os import os
import re
import subprocess import subprocess
import sys import sys
import yaml import yaml
@ -21,6 +22,7 @@ import yaml
import os_doc_tools import os_doc_tools
DEVNULL = open(os.devnull, 'wb') DEVNULL = open(os.devnull, 'wb')
MAXLINELENGTH = 78
def use_help_flag(os_command): def use_help_flag(os_command):
@ -33,28 +35,35 @@ def use_help_flag(os_command):
return os_command == "swift" or "-manage" in os_command return os_command == "swift" or "-manage" in os_command
def quote_xml(line): def quote_rst(line):
"""Convert special characters for XML output.""" """Convert special characters for RST output."""
line = line.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;') line = line.replace('\\', '\\\\').replace('`', '\\`').replace('*', '\\*')
if '--' in line:
line = re.sub(r'(--[^ .\'\\]*)', r":option:`\1`", line)
# work around for "`--`" at murano
line = line.replace('\\`:option:`--`\\`', '```--```')
if 'DEPRECATED!' in line: if 'DEPRECATED!' in line:
line = line.replace('DEPRECATED!', '<emphasis>DEPRECATED!</emphasis>') line = line.replace('DEPRECATED!', '**DEPRECATED!**')
elif 'DEPRECATED' in line: elif 'DEPRECATED' in line:
line = line.replace('DEPRECATED', '<emphasis>DEPRECATED</emphasis>') line = line.replace('DEPRECATED', '**DEPRECATED**')
if 'env[' in line: if 'env[' in line:
line = line.replace('env[', '<code>env[').replace(']', ']</code>') line = line.replace('env[', '``env[').replace(']', ']``')
# work around for "Default=env[...]" at cinder
line = line.replace('=``', '= ``')
return line return line
def generate_heading(os_command, api_name, title, os_file): def generate_heading(os_command, api_name, title, os_file):
"""Write DocBook file header. """Write RST file header.
:param os_command: client command to document :param os_command: client command to document
:param api_name: string description of the API of os_command :param api_name: string description of the API of os_command
:param os_file: open filehandle for output of DocBook file :param os_file: open filehandle for output of RST file
""" """
try: try:
@ -70,72 +79,41 @@ def generate_heading(os_command, api_name, title, os_file):
print("Documenting '%s help (version %s)'" % (os_command, version)) print("Documenting '%s help (version %s)'" % (os_command, version))
if use_help_flag(os_command): os_file.write(".. ## WARNING ######################################\n")
help_str = "<replaceable>COMMAND</replaceable> <option>--help</option>" os_file.write(".. This file is automatically generated, do not edit\n")
else: os_file.write(".. #################################################\n\n")
help_str = "<option>help</option> <replaceable>COMMAND</replaceable>" format_heading(title, 1, os_file)
header1 = """<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<chapter xmlns=\"http://docbook.org/ns/docbook\"
xmlns:xi=\"http://www.w3.org/2001/XInclude\"
xmlns:xlink=\"http://www.w3.org/1999/xlink\"
version=\"5.0\"
xml:id=\"%(os_command)sclient_commands\">
<!-- This file is automatically generated, do not edit -->
<?dbhtml stop-chunking?>
<title>%(title)s</title>\n"""
if os_command == "openstack":
header2 = """
<para>The <command>%(os_command)s</command> client is a common
OpenStack command-line interface (CLI).\n"""
else:
header2 = """
<para>The <command>%(os_command)s</command> client is the command-line
interface (CLI) for the %(api_name)s and its extensions.\n"""
header3 = """
This chapter documents <command>%(os_command)s</command> version
<literal>%(version)s</literal>.
</para>
<para>For help on a specific <command>%(os_command)s</command>
command, enter:
</para>
<screen><prompt>$</prompt> <userinput><command>%(os_command)s</command> \
%(help_str)s</userinput></screen>
<section xml:id=\"%(os_command)sclient_command_usage\">
<title>%(os_command)s usage</title>\n"""
if os_command == "keystone": if os_command == "keystone":
header_deprecation = """ os_file.write(".. warning::\n\n")
<warning> os_file.write(" The " + os_command + " CLI is deprecated\n")
<para>The %(os_command)s CLI is deprecated in favor of os_file.write(" in favor of python-openstackclient.\n")
python-openstackclient. For more information on os_file.write(" For more information, see :doc:`openstack`.\n")
python-openstackclient, please see os_file.write(" For a Python library, continue using\n")
<xref linkend="openstack_cli_identity_api_v2" /> and os_file.write(" python-" + os_command + "client.\n\n")
<xref linkend="openstack_cli_with_identity_api_v3" />.
For a Python library, continue
using python-%(os_command)sclient.</para>
</warning>\n"""
else:
header_deprecation = None
format_dict = { if os_command == "openstack":
"os_command": os_command, os_file.write("The openstack client is a common OpenStack")
"api_name": api_name, os_file.write("command-line interface (CLI).\n\n")
"title": title, else:
"version": version, os_file.write("The " + os_command + " client is the command-line ")
"help_str": help_str os_file.write("interface (CLI) for\n")
} os_file.write("the " + api_name + " and its extensions.\n\n")
os_file.write(header1 % format_dict)
if header_deprecation: os_file.write("This chapter documents :command:`" + os_command + "` ")
os_file.write(header_deprecation % format_dict) os_file.write("version ``" + version + "``.\n\n")
os_file.write(header2 % format_dict)
os_file.write(header3 % format_dict) os_file.write("For help on a specific :command:`" + os_command + "` ")
os_file.write("command, enter:\n\n")
os_file.write(".. code-block:: console\n\n")
if use_help_flag(os_command):
os_file.write(" $ " + os_command + " COMMAND --help\n\n")
else:
os_file.write(" $ " + os_command + " help COMMAND\n\n")
os_file.write(".. _" + os_command + "_command_usage:\n\n")
format_heading(os_command + " usage", 2, os_file)
def is_option(string): def is_option(string):
@ -233,13 +211,42 @@ def extract_options(line):
return split_line return split_line
def format_table(title, lines, os_file): def format_heading(heading, level, os_file):
"""Nicely print section of lines.""" """Nicely print heading.
:param heading: heading strings
:param level: heading level
:param os_file: open filehandle for output of RST file
"""
if level == 1:
os_file.write("=" * len(heading) + "\n")
os_file.write(heading + "\n")
if level == 1:
os_file.write("=" * len(heading) + "\n\n")
elif level == 2:
os_file.write("~" * len(heading) + "\n\n")
elif level == 3:
os_file.write("-" * len(heading) + "\n\n")
else:
os_file.write("\n")
return
def format_help(title, lines, os_file):
"""Nicely print section of lines.
:param title: help title, if exist
:param lines: strings to format
:param os_file: open filehandle for output of RST file
"""
close_entry = False close_entry = False
os_file.write(" <variablelist wordsize=\"10\">\n")
if title: if title:
os_file.write(" <title>%s</title>\n" % title) format_heading(title, 3, os_file)
for line in lines: for line in lines:
if not line or line[0] != ' ': if not line or line[0] != ' ':
@ -252,9 +259,13 @@ def format_table(title, lines, os_file):
# on next line # on next line
# If there are more than 8 spaces, let's treat it as # If there are more than 8 spaces, let's treat it as
# explanation. # explanation.
if line.startswith(' '): if line.startswith(' '):
# Explanation # Explanation
os_file.write(" %s\n" % quote_xml(line.lstrip(' '))) xline = quote_rst(line.lstrip(' '))
if len(xline) > (MAXLINELENGTH - 2):
# check niceness
xline = xline.replace(' ', '\n ')
os_file.write(" " + xline + "\n")
continue continue
# Now we have a command or parameter to handle # Now we have a command or parameter to handle
split_line = extract_options(line) split_line = extract_options(line)
@ -262,31 +273,41 @@ def format_table(title, lines, os_file):
if not close_entry: if not close_entry:
close_entry = True close_entry = True
else: else:
os_file.write(" </para>\n") os_file.write("\n")
os_file.write(" </listitem>\n")
os_file.write(" </varlistentry>\n") xline = split_line[0]
# check niceness work around for long option name
if len(xline) > (MAXLINELENGTH - 4):
xline = xline.replace(', -', ',``\n\n``-')
# check niceness work around for long option name, openstack
xline = xline.replace('--nic <net-id=net-uuid,v4-fixed-ip',
'--nic <net-id=net-uuid,``\n\n``v4-fixed-ip')
# check niceness work around for long option name, glance
xline = xline.replace('--sort-key {name,status,container',
'--sort-key {name,status,``\n\n``container')
os_file.write("``" + xline + "``\n")
os_file.write(" <varlistentry>\n")
os_file.write(" <term><command>%s</command></term>\n"
% quote_xml(split_line[0]))
os_file.write(" <listitem>\n")
os_file.write(" <para>\n")
if len(split_line) > 1: if len(split_line) > 1:
os_file.write(" %s\n" % quote_xml(split_line[1])) xline = quote_rst(split_line[1])
if len(xline) > (MAXLINELENGTH - 2):
# check niceness
xline = xline.replace(' ', '\n ')
os_file.write(" " + xline + "\n")
os_file.write(" </para>\n") os_file.write("\n")
os_file.write(" </listitem>\n")
os_file.write(" </varlistentry>\n")
os_file.write(" </variablelist>\n")
return return
def generate_command(os_command, os_file): def generate_command(os_command, os_file):
"""Convert os_command --help to DocBook. """Convert os_command --help to RST.
:param os_command: client command to document :param os_command: client command to document
:param os_file: open filehandle for output of DocBook file :param os_file: open filehandle for output of RST file
""" """
if os_command == "glance": if os_command == "glance":
@ -300,13 +321,11 @@ def generate_command(os_command, os_file):
ignore_next_lines = False ignore_next_lines = False
next_line_screen = True next_line_screen = True
next_line_screen = True
line_index = -1 line_index = -1
in_screen = False in_screen = False
subcommands = 'complete' subcommands = 'complete'
for line in help_lines: for line in help_lines:
line_index += 1 line_index += 1
xline = quote_xml(line)
if line and line[0] != ' ': if line and line[0] != ' ':
# XXX: Might have whitespace before!! # XXX: Might have whitespace before!!
if '<subcommands>' in line: if '<subcommands>' in line:
@ -315,69 +334,52 @@ def generate_command(os_command, os_file):
if 'Positional arguments' in line: if 'Positional arguments' in line:
ignore_next_lines = True ignore_next_lines = True
next_line_screen = True next_line_screen = True
os_file.write("</computeroutput></screen>\n") os_file.write("\n\n")
in_screen = False in_screen = False
if os_command != "glance": if os_command != "glance":
format_table('Subcommands', format_help('Subcommands',
help_lines[line_index + 2:], os_file) help_lines[line_index + 2:], os_file)
continue continue
if line.startswith(('Optional arguments:', 'Optional:', if line.startswith(('Optional arguments:', 'Optional:',
'Options:', 'optional arguments')): 'Options:', 'optional arguments')):
if in_screen: if in_screen:
os_file.write("</computeroutput></screen>\n") os_file.write("\n\n")
in_screen = False in_screen = False
os_file.write(" </section>\n") os_file.write(".. _" + os_command + "_command_options:\n\n")
os_file.write(" <section ") format_heading(os_command + " optional arguments", 2, os_file)
os_file.write("xml:id=\"%sclient_command_optional\">\n" format_help('', help_lines[line_index + 1:], os_file)
% os_command)
os_file.write(" <title>%s optional arguments</title>\n"
% os_command)
format_table('', help_lines[line_index + 1:],
os_file)
next_line_screen = True next_line_screen = True
ignore_next_lines = True ignore_next_lines = True
continue continue
# sahara # magnum and sahara
if line.startswith('Common auth options'): if line.startswith('Common auth options'):
if in_screen: if in_screen:
os_file.write("</computeroutput></screen>\n") os_file.write("\n\n")
in_screen = False in_screen = False
os_file.write(" </section>\n") os_file.write("\n")
os_file.write(" <section ") os_file.write(os_command)
os_file.write("xml:id=\"%sclient_command_common_auth\">\n" os_file.write(".. _" + os_command + "_common_auth:\n\n")
% os_command) format_heading(os_command + " common authentication arguments",
os_file.write(" <title>%s common authentication " 2, os_file)
"arguments</title>\n" format_help('', help_lines[line_index + 1:], os_file)
% os_command)
format_table('', help_lines[line_index + 1:],
os_file)
next_line_screen = True next_line_screen = True
ignore_next_lines = True ignore_next_lines = True
continue continue
# neutron # neutron
if line.startswith('Commands for API v2.0:'): if line.startswith('Commands for API v2.0:'):
if in_screen: if in_screen:
os_file.write("</computeroutput></screen>\n") os_file.write("\n\n")
in_screen = False in_screen = False
os_file.write(" </section>\n") os_file.write(".. _" + os_command + "_common_api_v2:\n\n")
os_file.write(" <section ") format_heading(os_command + " API v2.0 commands", 2, os_file)
os_file.write("xml:id=\"%sclient_command_api_2_0\">\n" format_help('', help_lines[line_index + 1:], os_file)
% os_command)
os_file.write(" <title>%s API v2.0 commands</title>\n"
% os_command)
format_table('', help_lines[line_index + 1:],
os_file)
next_line_screen = True next_line_screen = True
ignore_next_lines = True ignore_next_lines = True
continue continue
# swift # swift
if line.startswith('Examples:'): if line.startswith('Examples:'):
os_file.write(" </section>\n") os_file.write(".. _" + os_command + "_examples:\n\n")
os_file.write(" <section ") format_heading(os_command + " examples", 2, os_file)
os_file.write("xml:id=\"%sclient_command_examples\">\n"
% os_command)
os_file.write(" <title>%s examples</title>\n"
% os_command)
next_line_screen = True next_line_screen = True
ignore_next_lines = False ignore_next_lines = False
continue continue
@ -385,31 +387,31 @@ def generate_command(os_command, os_file):
continue continue
if not ignore_next_lines: if not ignore_next_lines:
if next_line_screen: if next_line_screen:
os_file.write(" <screen><computeroutput>%s" % xline) os_file.write(".. code-block:: console\n\n")
os_file.write(" " + line)
next_line_screen = False next_line_screen = False
in_screen = True in_screen = True
elif line: elif line:
os_file.write("\n%s" % xline.rstrip()) os_file.write("\n " + line.rstrip())
# subcommands (select bash-completion, complete for bash-completion) # subcommands (select bash-completion, complete for bash-completion)
if 'bash-completion' in line: if 'bash-completion' in line:
subcommands = 'bash-completion' subcommands = 'bash-completion'
if in_screen: if in_screen:
os_file.write("</computeroutput></screen>\n") os_file.write("\n\n")
os_file.write(" </section>\n")
return subcommands return subcommands
def generate_subcommand(os_command, os_subcommand, os_file, extra_params, def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
suffix, title_suffix): suffix, title_suffix):
"""Convert os_command help os_subcommand to DocBook. """Convert os_command help os_subcommand to RST.
:param os_command: client command to document :param os_command: client command to document
:param os_subcommand: client subcommand to document :param os_subcommand: client subcommand to document
:param os_file: open filehandle for output of DocBook file :param os_file: open filehandle for output of RST file
:param extra_params: Extra parameter to pass to os_command :param extra_params: Extra parameter to pass to os_command
:param suffix: Extra suffix to add to xml:id :param suffix: Extra suffix to add to link ID
:param title_suffix: Extra suffix for title :param title_suffix: Extra suffix for title
""" """
@ -440,17 +442,14 @@ def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
help_lines = help_lines.split('\n') help_lines = help_lines.split('\n')
os_subcommandid = os_subcommand.replace(' ', '_') os_subcommandid = os_subcommand.replace(' ', '_')
os_file.write(" <section xml:id=\"%sclient_subcommand_%s%s\">\n" os_file.write(".. _" + os_command + "_" + os_subcommandid + suffix)
% (os_command, os_subcommandid, suffix)) os_file.write(":\n\n")
os_file.write(" <title>%s %s%s</title>\n" format_heading(os_command + " " + os_subcommand + title_suffix, 2, os_file)
% (os_command, os_subcommand, title_suffix))
if os_command == "swift": if os_command == "swift":
next_line_screen = False next_line_screen = False
os_file.write("\n <screen><computeroutput>Usage: swift %s" os_file.write(".. code-block:: console\n\n")
"</computeroutput></screen>" os_file.write("Usage: swift " + os_subcommand + "\n\n")
% (os_subcommand))
os_file.write("\n <para>")
in_para = True in_para = True
else: else:
next_line_screen = True next_line_screen = True
@ -477,39 +476,47 @@ def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
'optional arguments')): 'optional arguments')):
if in_para: if in_para:
in_para = False in_para = False
os_file.write("\n </para>") os_file.write("\n")
if line.startswith(('Positional arguments', if line.startswith(('Positional arguments',
'positional arguments')): 'positional arguments')):
format_table('Positional arguments', format_help('Positional arguments',
help_lines[line_index + 1:], os_file) help_lines[line_index + 1:], os_file)
skip_lines = True skip_lines = True
continue continue
elif line.startswith(('Optional arguments:', elif line.startswith(('Optional arguments:',
'optional arguments')): 'optional arguments')):
format_table('Optional arguments', format_help('Optional arguments',
help_lines[line_index + 1:], os_file) help_lines[line_index + 1:], os_file)
break break
else: else:
format_table('Arguments', help_lines[line_index + 1:], os_file) format_help('Arguments', help_lines[line_index + 1:], os_file)
break break
if skip_lines: if skip_lines:
continue continue
if not line: if not line:
if not in_para: if not in_para:
os_file.write("</computeroutput></screen>") os_file.write("\n")
os_file.write("\n <para>")
in_para = True in_para = True
continue continue
xline = quote_xml(line)
if next_line_screen: if next_line_screen:
os_file.write(" <screen><computeroutput>%s" % xline) os_file.write(".. code-block:: console\n\n")
os_file.write(" " + line + "\n")
next_line_screen = False next_line_screen = False
elif line.startswith(' '):
# ceilometer alarm-gnocchi-aggregation-by-metrics-threshold-create
# has 7 white space indentation
if not line.isspace():
# skip blank line, such as "trove help cluster-grow" command.
os_file.write(" " + line + "\n")
else: else:
os_file.write("\n%s" % (xline)) xline = quote_rst(line)
if (len(xline) > MAXLINELENGTH):
# check niceness
xline = xline.replace(' ', '\n')
os_file.write(xline + "\n")
if in_para: if in_para:
os_file.write("\n </para>\n") os_file.write("\n")
os_file.write(" </section>\n")
def discover_subcommands(os_command, subcommands, extra_params): def discover_subcommands(os_command, subcommands, extra_params):
@ -558,14 +565,14 @@ def discover_subcommands(os_command, subcommands, extra_params):
def generate_subcommands(os_command, os_file, subcommands, extra_params, def generate_subcommands(os_command, os_file, subcommands, extra_params,
suffix, title_suffix): suffix, title_suffix):
"""Convert os_command help subcommands for all subcommands to DocBook. """Convert os_command help subcommands for all subcommands to RST.
:param os_command: client command to document :param os_command: client command to document
:param os_file: open filehandle for output of DocBook file :param os_file: open filehandle for output of RST file
:param subcommands: list or type ('complete' or 'bash-completion') :param subcommands: list or type ('complete' or 'bash-completion')
of subcommands to document of subcommands to document
:param extra_params: Extra parameter to pass to os_command. :param extra_params: Extra parameter to pass to os_command.
:param suffix: Extra suffix to add to xml:id :param suffix: Extra suffix to add to link ID
:param title_suffix: Extra suffix for title :param title_suffix: Extra suffix for title
""" """
for subcommand in subcommands: for subcommand in subcommands:
@ -576,14 +583,14 @@ def generate_subcommands(os_command, os_file, subcommands, extra_params,
def discover_and_generate_subcommands(os_command, os_file, subcommands, def discover_and_generate_subcommands(os_command, os_file, subcommands,
extra_params, suffix, title_suffix): extra_params, suffix, title_suffix):
"""Convert os_command help subcommands for all subcommands to DocBook. """Convert os_command help subcommands for all subcommands to RST.
:param os_command: client command to document :param os_command: client command to document
:param os_file: open filehandle for output of DocBook file :param os_file: open filehandle for output of RST file
:param subcommands: list or type ('complete' or 'bash-completion') :param subcommands: list or type ('complete' or 'bash-completion')
of subcommands to document of subcommands to document
:param extra_params: Extra parameter to pass to os_command. :param extra_params: Extra parameter to pass to os_command.
:param suffix: Extra suffix to add to xml:id :param suffix: Extra suffix to add to link ID
:param title_suffix: Extra suffix for title :param title_suffix: Extra suffix for title
""" """
subcommands = discover_subcommands(os_command, subcommands, extra_params) subcommands = discover_subcommands(os_command, subcommands, extra_params)
@ -591,16 +598,6 @@ def discover_and_generate_subcommands(os_command, os_file, subcommands,
suffix, title_suffix) suffix, title_suffix)
def generate_end(os_file):
"""Finish writing file.
:param os_file: open filehandle for output of DocBook file
"""
print("Finished.\n")
os_file.write("</chapter>\n")
def get_clients(): def get_clients():
"""Load client definitions from the resource file.""" """Load client definitions from the resource file."""
fname = os.path.join(os.path.dirname(__file__), fname = os.path.join(os.path.dirname(__file__),
@ -628,21 +625,18 @@ def document_single_project(os_command, output_dir):
api_name = '' api_name = ''
title = data.get('title', '') title = data.get('title', '')
out_filename = "ch_cli_" + os_command + "_commands.xml" out_filename = os_command + ".rst"
out_file = open(os.path.join(output_dir, out_filename), 'w') out_file = open(os.path.join(output_dir, out_filename), 'w')
generate_heading(os_command, api_name, title, out_file) generate_heading(os_command, api_name, title, out_file)
subcommands = generate_command(os_command, out_file) subcommands = generate_command(os_command, out_file)
if os_command == 'cinder': if os_command == 'cinder':
out_file.write(""" format_heading("Block Storage API v1 commands (DEPRECATED)",
<section xml:id=\"cinder_cli_v1\"> 2, out_file)
<title>Block Storage API v1 commands (DEPRECATED)</title>\n""")
discover_and_generate_subcommands(os_command, out_file, subcommands, discover_and_generate_subcommands(os_command, out_file, subcommands,
None, "", "") None, "", "")
elif os_command == 'openstack': elif os_command == 'openstack':
out_file.write(""" format_heading("OpenStack with Identity API v2 commands", 2, out_file)
<section xml:id=\"openstack_cli_identity_api_v2\">
<title>OpenStack with Identity API v2 commands</title>\n""")
auth_type_token = ["--os-auth-type", "token"] auth_type_token = ["--os-auth-type", "token"]
identity_api_v2 = ["--os-identity-api-version", "2"] identity_api_v2 = ["--os-identity-api-version", "2"]
extra_params = auth_type_token + identity_api_v2 extra_params = auth_type_token + identity_api_v2
@ -651,9 +645,7 @@ def document_single_project(os_command, output_dir):
generate_subcommands(os_command, out_file, subcommands_v2, generate_subcommands(os_command, out_file, subcommands_v2,
extra_params, "_with_identity_api_v2", "") extra_params, "_with_identity_api_v2", "")
elif os_command == 'glance': elif os_command == 'glance':
out_file.write(""" format_heading("Image service API v1 commands", 2, out_file)
<section xml:id=\"glance_cli_v1\">
<title>Image service API v1 commands</title>\n""")
discover_and_generate_subcommands(os_command, out_file, subcommands, discover_and_generate_subcommands(os_command, out_file, subcommands,
["--os-image-api-version", "1"], ["--os-image-api-version", "1"],
"_v1", " (v1)") "_v1", " (v1)")
@ -663,40 +655,37 @@ def document_single_project(os_command, output_dir):
# Print subcommands for different API versions # Print subcommands for different API versions
if os_command == 'cinder': if os_command == 'cinder':
out_file.write(" </section>\n") out_file.write("\n")
out_file.write(""" format_heading("Block Storage API v2 commands", 2, out_file)
<section xml:id=\"cinder_cli_v2\">
<title>Block Storage API v2 commands</title> out_file.write("You can select an API version to use by adding the\n")
<para> out_file.write(":option:`--os-volume-api-version` parameter or by\n")
You can select an API version to use by adding the out_file.write("setting the corresponding environment variable:\n\n")
<parameter>--os-volume-api-version</parameter> parameter or by setting
the corresponding environment variable:\n""") out_file.write(".. code-block:: console\n\n")
out_file.write("<screen><prompt>$</prompt> <userinput>" out_file.write(" export OS_VOLUME_API_VERSION=2\n\n")
"export OS_VOLUME_API_VERSION=2</userinput></screen>\n"
"</para>\n")
discover_and_generate_subcommands(os_command, out_file, subcommands, discover_and_generate_subcommands(os_command, out_file, subcommands,
["--os-volume-api-version", "2"], ["--os-volume-api-version", "2"],
"_v2", " (v2)") "_v2", " (v2)")
out_file.write(" </section>\n")
if os_command == 'openstack': if os_command == 'openstack':
# Print the additional subcommands possible by using v3 of identity API # Print the additional subcommands possible by using v3 of identity API
out_file.write(""" out_file.write("\n")
</section>\n format_heading("OpenStack with Identity API v3 commands (diff)",
<section xml:id=\"openstack_cli_with_identity_api_v3\"> 2, out_file)
<title>OpenStack with Identity API v3 commands (diff)</title>
<para> out_file.write("You can select the Identity API version to use by\n")
You can select the Identity API version to use by adding the out_file.write("adding the :option:`--os-identity-api-version`\n")
<parameter>--os-identity-api-version</parameter> parameter or by setting out_file.write("parameter or by setting the corresponding\n")
the corresponding environment variable:\n""") out_file.write("environment variable:\n\n")
out_file.write("<screen><prompt>$</prompt> <userinput>"
"export OS_IDENTITY_API_VERSION=3</userinput>" out_file.write(".. code-block:: console\n\n")
"</screen>\n</para>\n") out_file.write(" export OS_IDENTITY_API_VERSION=3\n\n")
out_file.write("<para>\n"
"This section documents only the difference in" out_file.write("This section documents only the difference in\n")
" subcommands available for the openstack client when" out_file.write("subcommands available for the openstack client\n")
" the identity API version is changed from v2 to v3.\n" out_file.write("when the Identity API version is changed from\n")
"</para>\n") out_file.write("v2 to v3.\n\n")
identity_api_v3 = ["--os-identity-api-version", "3"] identity_api_v3 = ["--os-identity-api-version", "3"]
extra_params = auth_type_token + identity_api_v3 extra_params = auth_type_token + identity_api_v3
@ -707,30 +696,24 @@ def document_single_project(os_command, output_dir):
generate_subcommands(os_command, out_file, subcommands_delta, generate_subcommands(os_command, out_file, subcommands_delta,
extra_params, "_with_identity_api_v3", extra_params, "_with_identity_api_v3",
" (Identity API v3)") " (Identity API v3)")
out_file.write(" </section>\n")
if os_command == 'glance': if os_command == 'glance':
out_file.write(""" out_file.write("\n")
</section>\n format_heading("Image service API v2 commands", 2, out_file)
<section xml:id=\"glance_cli_v2\"> out_file.write("You can select an API version to use by adding the\n")
<title>Image service API v2 commands</title> out_file.write(":option:`--os-image-api-version` parameter or by\n")
<para> out_file.write("setting the corresponding environment variable:\n\n")
You can select an API version to use by adding the
<parameter>--os-image-api-version</parameter> parameter or by setting out_file.write(".. code-block:: console\n\n")
the corresponding environment variable:\n""") out_file.write(" export OS_IMAGE_API_VERSION=2\n\n")
out_file.write("<screen><prompt>$</prompt> <userinput>"
"export OS_IMAGE_API_VERSION=2</userinput></screen>\n"
"</para>\n")
discover_and_generate_subcommands(os_command, out_file, subcommands, discover_and_generate_subcommands(os_command, out_file, subcommands,
["--os-image-api-version", "2"], ["--os-image-api-version", "2"],
"_v2", " (v2)") "_v2", " (v2)")
out_file.write(" </section>\n")
if os_command == 'glance': if os_command == 'glance':
out_file.write(" <xi:include " out_file.write(".. include:: glance_property_keys.rst\n")
"href=\"../section_cli_glance_property_keys.xml\"/>\n")
generate_end(out_file) print("Finished.\n")
out_file.close() out_file.close()
@ -744,7 +727,7 @@ def main():
manage_clients = sorted([x for x in clients if x.endswith('-manage')]) manage_clients = sorted([x for x in clients if x.endswith('-manage')])
all_clients = api_clients + manage_clients all_clients = api_clients + manage_clients
parser = argparse.ArgumentParser(description="Generate DocBook XML files " parser = argparse.ArgumentParser(description="Generate RST files "
"to document python-PROJECTclients.") "to document python-PROJECTclients.")
parser.add_argument('client', nargs='?', parser.add_argument('client', nargs='?',
help="OpenStack command to document. One of: " + help="OpenStack command to document. One of: " +

View File

@ -0,0 +1,6 @@
---
features:
- Update CLI Reference generation tool for RST.
To migrate CLI Reference from DocBook to RST,
output the documentation in RST format,
with a few work arounds for RST/Sphinx specific issues.