diff --git a/docs/templates/man.j2 b/docs/templates/man.j2 new file mode 100644 index 0000000000..bb92ec2999 --- /dev/null +++ b/docs/templates/man.j2 @@ -0,0 +1,104 @@ +ansible{% if cli != 'adhoc' %}-{{cli}}{% endif %}(1) +================== +:doctype:manpage +:man source: Ansible +:man version: %VERSION% +:man manual: System administration commands + +NAME +---- +ansible{% if cli != 'adhoc' %}-{{cli}}{% endif %} - {{short_desc|default('')}} + + +SYNOPSIS +-------- +{{ usage }} + + +DESCRIPTION +----------- +{{ long_desc }} + + +{% if arguments %} +ARGUMENTS +--------- + +{% for arg in arguments %} +{{ arg['name'] }} + +{{ arg['desc'] }} + +{% endfor %} +{% endif %} + +OPTIONS +------- + +{% for option in options|sort(attribute='options') %} +{% for switch in option['options'] %}*{{switch}}* {% if option['arg'] %}'{{option['arg']}}'{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}:: + +{{ option['desc'] }} +{% endfor %} + +{% if inv_opts %} +INVENTORY +--------- + +Ansible stores the hosts it can potentially operate on in an inventory. +This can be an YAML file, ini-like file, a script, directory, list, etc. +For additional options, see the documentation on http://docs.ansible.com/. + +{% endif %} +ENVIRONMENT +----------- + +The following environment variables may be specified. + +{% if inv_opts %} +ANSIBLE_INVENTORY -- Override the default ansible inventory file + +{% endif %} +{% if run_opts %} +ANSIBLE_LIBRARY -- Override the default ansible module library path + +{% endif %} +ANSIBLE_CONFIG -- Override the default ansible config file + +Many more are available for most options in ansible.cfg + + +FILES +----- + +{% if inv_opts %} +/etc/ansible/hosts -- Default inventory file + +{% endif %} +/etc/ansible/ansible.cfg -- Config file, used if present + +~/.ansible.cfg -- User config file, overrides the default config if present + + +AUTHOR +------ + +Ansible was originally written by Michael DeHaan. +See the AUTHORS file for a complete list of contributors. + + +COPYRIGHT +--------- + +Copyright © 2017 Red Hat, Inc. +Ansible is released under the terms of the GPLv3 License. + + +SEE ALSO +-------- + + {% for other in cli_list|sort %}{% if other != cli %}*ansible{% if other != 'adhoc' %}-{{other}}{% endif %}*(1){% if not loop.last %}, {% endif %}{% endif %}{% endfor %} + +Extensive documentation is available in the documentation site: +. IRC and mailing list info can be found +in file CONTRIBUTING.md, available in: diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index cdfd4a2b89..aa3c8b26f6 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -90,7 +90,6 @@ class InvalidOptsParser(SortedOptParser): except optparse.BadOptionError: pass - class CLI(with_metaclass(ABCMeta, object)): ''' code behind bin/ansible* programs ''' @@ -284,15 +283,11 @@ class CLI(with_metaclass(ABCMeta, object)): @staticmethod def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False, - async_opts=False, connect_opts=False, subset_opts=False, check_opts=False, inventory_opts=False, epilog=None, fork_opts=False, - runas_prompt_opts=False): + async_opts=False, connect_opts=False, subset_opts=False, check_opts=False, inventory_opts=False, epilog=None, fork_opts=False, runas_prompt_opts=False, desc=None): ''' create an options parser for most ansible scripts ''' - # TODO: implement epilog parsing - # OptionParser.format_epilog = lambda self, formatter: self.epilog - # base opts - parser = SortedOptParser(usage, version=CLI.version("%prog")) + parser = SortedOptParser(usage, version=CLI.version("%prog"), description=desc, epilog=epilog) parser.add_option('-v','--verbose', dest='verbosity', default=C.DEFAULT_VERBOSITY, action="count", help="verbose mode (-vvv for more, -vvvv to enable connection debugging)") @@ -669,3 +664,52 @@ class CLI(with_metaclass(ABCMeta, object)): if os.pathsep in data: data = data.split(os.pathsep)[0] return data + + def _opt_doc_list(self, action=None): + ''' generate options docs ''' + + if action: + self.args.append(action) + self.set_action() + + results = [] + for opt in self.parser.option_list: + res = { + 'desc': opt.help, + 'options': opt._short_opts + opt._long_opts + } + if opt.action == 'store': + res['arg'] = opt.dest.upper() + results.append(res) + + return results + + def opts_docs(self, args=None): + ''' generate doc structure from options ''' + + # cli name + name = os.path.basename(sys.argv[0]) + if '-' in name: + name = name.split('-')[1] + else: + name = 'adhoc' + + # cli info + docs = { + 'cli': name, + 'usage': self.parser.usage, + 'short_desc': self.parser.description + } + + if self.VALID_ACTIONS: + myopts = [] + for action in self.VALID_ACTIONS: + newopts = self._opt_doc_list(action) + for nopt in newopts: + if nopt not in myopts: + myopts.append(nopt) + docs['options'] = myopts + else: + docs['options'] = self._opt_doc_list() + + return docs diff --git a/lib/ansible/cli/adhoc.py b/lib/ansible/cli/adhoc.py index d5d9ed1b4d..76b9d881b2 100644 --- a/lib/ansible/cli/adhoc.py +++ b/lib/ansible/cli/adhoc.py @@ -46,7 +46,7 @@ except ImportError: ######################################################## class AdHocCLI(CLI): - ''' code behind ansible ad-hoc cli''' + ''' Ad-hoc Ansible allows you to define and run a single task 'playbook' against a set of hosts ''' def parse(self): ''' create an options parser for bin/ansible ''' @@ -63,6 +63,8 @@ class AdHocCLI(CLI): vault_opts=True, fork_opts=True, module_opts=True, + desc="Define and run a single task 'playbook' against a set of hosts", + epilog="Some modules do not make sense in Ad-Hoc (include, meta, etc)", ) # options unique to ansible ad-hoc @@ -92,7 +94,7 @@ class AdHocCLI(CLI): ) def run(self): - ''' use Runner lib to do SSH things ''' + ''' create and execute the single task playbook ''' super(AdHocCLI, self).run() diff --git a/lib/ansible/cli/console.py b/lib/ansible/cli/console.py index eb86760686..5bf9d9e84d 100644 --- a/lib/ansible/cli/console.py +++ b/lib/ansible/cli/console.py @@ -79,7 +79,7 @@ class ConsoleCLI(CLI, cmd.Cmd): def parse(self): self.parser = CLI.base_parser( - usage='%prog [options]', + usage='%prog [] [options]', runas_opts=True, inventory_opts=True, connect_opts=True, @@ -87,6 +87,8 @@ class ConsoleCLI(CLI, cmd.Cmd): vault_opts=True, fork_opts=True, module_opts=True, + desc="REPL console for executing Ansible tasks.", + epilog="This is not a live session/connection, each task executes in the background and returns it's results." ) # options unique to shell diff --git a/lib/ansible/cli/doc.py b/lib/ansible/cli/doc.py index 8e45e7cb66..d5cc670bf9 100644 --- a/lib/ansible/cli/doc.py +++ b/lib/ansible/cli/doc.py @@ -50,9 +50,10 @@ class DocCLI(CLI): def parse(self): self.parser = CLI.base_parser( - usage='usage: %prog [options] [plugin ...]', - epilog='Show Ansible plugin documentation', + usage='usage: %prog [options] [plugin]', module_opts=True, + desc="plugin documentation tool", + epilog="See man pages for Ansbile CLI options or website for tutorials https://docs.ansible.com" ) self.parser.add_option("-l", "--list", action="store_true", default=False, dest='list_dir', diff --git a/lib/ansible/cli/playbook.py b/lib/ansible/cli/playbook.py index 073379b1ab..349841159e 100644 --- a/lib/ansible/cli/playbook.py +++ b/lib/ansible/cli/playbook.py @@ -50,7 +50,7 @@ class PlaybookCLI(CLI): # create parser for CLI options parser = CLI.base_parser( - usage = "%prog playbook.yml", + usage = "%prog [options] playbook.yml [playbook2 ...]", connect_opts=True, meta_opts=True, runas_opts=True, @@ -61,6 +61,7 @@ class PlaybookCLI(CLI): vault_opts=True, fork_opts=True, module_opts=True, + desc="Runs Ansible playbooks, executing the defined tasks on the targeted hosts.", ) # ansible playbook specific opts diff --git a/lib/ansible/cli/pull.py b/lib/ansible/cli/pull.py index 1f6298bcda..ccc9eae89e 100644 --- a/lib/ansible/cli/pull.py +++ b/lib/ansible/cli/pull.py @@ -66,6 +66,7 @@ class PullCLI(CLI): inventory_opts=True, module_opts=True, runas_prompt_opts=True, + desc="pulls playbooks from a VCS repo and executes them for the local host", ) # options unique to pull diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py index 4326ff9c78..9a96e9e1a3 100644 --- a/lib/ansible/cli/vault.py +++ b/lib/ansible/cli/vault.py @@ -55,7 +55,8 @@ class VaultCLI(CLI): self.parser = CLI.base_parser( vault_opts=True, - usage = "usage: %%prog [%s] [--help] [options] vaultfile.yml" % "|".join(self.VALID_ACTIONS), + usage = "usage: %%prog [%s] [options] [vaultfile.yml]" % "|".join(self.VALID_ACTIONS), + desc = "encryption/decryption utility for Ansbile data files", epilog = "\nSee '%s --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]) )