summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorJan-Piet Mens <jpmens@gmail.com>2012-11-28 09:39:26 +0100
committerMichael DeHaan <michael.dehaan@gmail.com>2012-11-30 21:57:25 -0500
commit17f31a2a7974e861a6d9530e50bd89ab9db11816 (patch)
tree6a23672a1fbeca22185df0797cac0c7c7c9ced0e /bin
parentb8d6dec5ad0320d9a5642647f30d6c4edd050250 (diff)
downloadansible-17f31a2a7974e861a6d9530e50bd89ab9db11816.tar.gz
CLI: ansible-doc shows lists of modules & module docs on command-line
check path is directory added manpage & setup small cleanup shut up module_formatter in utils to avoid trace print on crud files in library
Diffstat (limited to 'bin')
-rwxr-xr-xbin/ansible-doc203
1 files changed, 203 insertions, 0 deletions
diff --git a/bin/ansible-doc b/bin/ansible-doc
new file mode 100755
index 0000000000..c82b3b1095
--- /dev/null
+++ b/bin/ansible-doc
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+
+# (c) 2012, Jan-Piet Mens <jpmens () gmail.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import sys
+import yaml
+import json
+import ast
+import textwrap
+import re
+import optparse
+import time
+import datetime
+from ansible import utils
+from ansible import errors
+from ansible.utils import module_docs
+import ansible.constants as C
+
+MODULEDIR = C.DEFAULT_MODULE_PATH
+
+_ITALIC = re.compile(r"I\(([^)]+)\)")
+_BOLD = re.compile(r"B\(([^)]+)\)")
+_MODULE = re.compile(r"M\(([^)]+)\)")
+_URL = re.compile(r"U\(([^)]+)\)")
+_CONST = re.compile(r"C\(([^)]+)\)")
+
+def tty_ify(text):
+
+ t = _ITALIC.sub("`" + r"\1" + "'", text) # I(word) => `word'
+ t = _BOLD.sub("*" + r"\1" + "*", t) # B(word) => *word*
+ t = _MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word]
+ t = _URL.sub(r"\1", t) # U(word) => word
+ t = _CONST.sub("`" + r"\1" + "'", t) # C(word) => `word'
+
+ return t
+
+def print_man(doc):
+
+ opt_indent=" "
+ print "> %s\n" % doc['module'].upper()
+
+ desc = "".join(doc['description'])
+
+ print "%s\n" % textwrap.fill(tty_ify(desc), initial_indent=" ", subsequent_indent=" ")
+
+ print "Options (= is mandatory):\n"
+
+ for o in doc['option_keys']:
+ opt = doc['options'][o]
+
+ if opt.get('required', False):
+ opt_leadin = "="
+ else:
+ opt_leadin = "-"
+
+ print "%s %s" % (opt_leadin, o)
+ desc = "".join(opt['description'])
+
+ if 'choices' in opt:
+ choices = ", ".join(opt['choices'])
+ desc = desc + " (Choices: " + choices + ")"
+ print "%s\n" % textwrap.fill(tty_ify(desc), initial_indent=opt_indent,
+ subsequent_indent=opt_indent)
+
+ if 'notes' in doc:
+ notes = "".join(doc['notes'])
+ print "Notes:%s\n" % textwrap.fill(tty_ify(notes), initial_indent=" ",
+ subsequent_indent=opt_indent)
+
+
+ for ex in doc['examples']:
+ print "%s%s" % (opt_indent, ex['code'])
+
+def print_snippet(doc):
+
+ desc = tty_ify("".join(doc['short_description']))
+ print "- name: %s" % (desc)
+ print " action: %s" % (doc['module'])
+
+ for o in doc['options']:
+ opt = doc['options'][o]
+ desc = tty_ify("".join(opt['description']))
+ s = o + "="
+ print " %-20s # %s" % (s, desc[0:60])
+
+def main():
+
+ p = optparse.OptionParser(
+ version='%prog 1.0',
+ usage='usage: %prog [options] [module...]',
+ description='Show Ansible module documentation',
+ )
+
+ p.add_option("-M", "--module-path",
+ action="store",
+ dest="module_path",
+ default=MODULEDIR,
+ help="Ansible modules/ directory")
+ p.add_option("-l", "--list",
+ action="store_true",
+ default=False,
+ dest='list_dir',
+ help='List available modules')
+ p.add_option("-s", "--snippet",
+ action="store_true",
+ default=False,
+ dest='show_snippet',
+ help='Show playbook snippet for specified module(s)')
+ p.add_option('-v', action='version', help='Show version number and exit')
+
+ (options, args) = p.parse_args()
+
+ if options.module_path is not None:
+ utils.plugins.vars_loader.add_directory(options.module_path)
+
+ if options.list_dir:
+ # list all modules
+ paths = utils.plugins.module_finder._get_paths()
+ module_list = []
+ for path in paths:
+ # os.system("ls -C %s" % (path))
+ if os.path.isdir(path):
+ for module in os.listdir(path):
+ module_list.append(module)
+
+ for module in sorted(module_list):
+
+ if module in module_docs.BLACKLIST_MODULES:
+ continue
+
+ filename = utils.plugins.module_finder.find_plugin(module)
+ try:
+ doc = utils.module_docs.get_docstring(filename)
+ desc = tty_ify(doc.get('short_description', '?'))
+ if len(desc) > 55:
+ desc = desc + '...'
+ print "%-20s %-60.60s" % (module, desc)
+ except:
+ sys.stderr.write("ERROR: module %s missing documentation\n" % module)
+ pass
+
+ sys.exit()
+
+ module_list = []
+
+ if len(args) == 0:
+ p.print_help()
+
+ for module in args:
+
+ filename = utils.plugins.module_finder.find_plugin(module)
+ if filename is None:
+ sys.stderr.write("module %s not found in %s\n" % (module,
+ utils.plugins.module_finder.print_paths()))
+ continue
+
+ if filename.endswith(".swp"):
+ continue
+
+ try:
+ doc = utils.module_docs.get_docstring(filename)
+ except:
+ sys.stderr.write("ERROR: module %s missing documentation\n" % module)
+ continue
+
+ if not doc is None:
+
+ all_keys = []
+ for (k,v) in doc['options'].iteritems():
+ all_keys.append(k)
+ all_keys = sorted(all_keys)
+ doc['option_keys'] = all_keys
+
+ doc['filename'] = filename
+ doc['docuri'] = doc['module'].replace('_', '-')
+ doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
+
+ if options.show_snippet:
+ print_snippet(doc)
+ else:
+ print_man(doc)
+ else:
+ sys.stderr.write("ERROR: module %s missing documentation\n" % module)
+
+if __name__ == '__main__':
+ main()