This commit is contained in:
bryan hunt
2015-07-27 11:57:58 +01:00
991 changed files with 76319 additions and 12784 deletions

View File

@@ -29,10 +29,26 @@ a module outside of the ansible program, locally, on the current machine.
Example:
$ ./hacking/test-module -m library/commands/shell -a "echo hi"
$ ./hacking/test-module -m lib/ansible/modules/core/commands/shell -a "echo hi"
This is a good way to insert a breakpoint into a module, for instance.
For more complex arguments such as the following yaml:
```yaml
parent:
child:
- item: first
val: foo
- item: second
val: boo
```
Use:
$ ./hacking/test-module -m module \
-a "{"parent": {"child": [{"item": "first", "val": "foo"}, {"item": "second", "val": "bar"}]}}"
Module-formatter
----------------

View File

@@ -4,7 +4,7 @@ set -e
# Get a list of authors ordered by number of commits
# and remove the commit count column
AUTHORS=$(git --no-pager shortlog -nse | cut -f 2- | sort -f)
AUTHORS=$(git --no-pager shortlog -nse --no-merges | cut -f 2- )
if [ -z "$AUTHORS" ] ; then
echo "Authors list was empty"
exit 1

86
hacking/env-setup Executable file → Normal file
View File

@@ -1,42 +1,80 @@
#!/bin/bash
# usage: source ./hacking/env-setup [-q]
# usage: source hacking/env-setup [-q]
# modifies environment for running Ansible from checkout
# Default values for shell variables we use
PYTHONPATH=${PYTHONPATH-""}
PATH=${PATH-""}
MANPATH=${MANPATH-""}
verbosity=${1-info} # Defaults to `info' if unspecified
if [ "$verbosity" = -q ]; then
verbosity=silent
fi
# When run using source as directed, $0 gets set to bash, so we must use $BASH_SOURCE
if [ -n "$BASH_SOURCE" ] ; then
HACKING_DIR=`dirname $BASH_SOURCE`
elif [ $(basename $0) = "env-setup" ]; then
HACKING_DIR=`dirname $0`
HACKING_DIR=$(dirname "$BASH_SOURCE")
elif [ $(basename -- "$0") = "env-setup" ]; then
HACKING_DIR=$(dirname "$0")
# Works with ksh93 but not pdksh
elif [ -n "$KSH_VERSION" ] && echo $KSH_VERSION | grep -qv '^@(#)PD KSH'; then
HACKING_DIR=$(dirname "${.sh.file}")
else
HACKING_DIR="$PWD/hacking"
fi
# The below is an alternative to readlink -fn which doesn't exist on OS X
# Source: http://stackoverflow.com/a/1678636
FULL_PATH=`python -c "import os; print(os.path.realpath('$HACKING_DIR'))"`
export ANSIBLE_HOME=`dirname "$FULL_PATH"`
FULL_PATH=$(python -c "import os; print(os.path.realpath('$HACKING_DIR'))")
export ANSIBLE_HOME=(dirname "$FULL_PATH")
PREFIX_PYTHONPATH="$ANSIBLE_HOME/lib"
PREFIX_PATH="$ANSIBLE_HOME/bin"
PREFIX_MANPATH="$ANSIBLE_HOME/docs/man"
[[ $PYTHONPATH != ${PREFIX_PYTHONPATH}* ]] && export PYTHONPATH=$PREFIX_PYTHONPATH:$PYTHONPATH
[[ $PATH != ${PREFIX_PATH}* ]] && export PATH=$PREFIX_PATH:$PATH
[[ $MANPATH != ${PREFIX_MANPATH}* ]] && export MANPATH=$PREFIX_MANPATH:$MANPATH
expr "$PYTHONPATH" : "${PREFIX_PYTHONPATH}.*" > /dev/null || export PYTHONPATH="$PREFIX_PYTHONPATH:$PYTHONPATH"
expr "$PATH" : "${PREFIX_PATH}.*" > /dev/null || export PATH="$PREFIX_PATH:$PATH"
expr "$MANPATH" : "${PREFIX_MANPATH}.*" > /dev/null || export MANPATH="$PREFIX_MANPATH:$MANPATH"
# Print out values unless -q is set
#
# Generate egg_info so that pkg_resources works
#
if [ $# -eq 0 -o "$1" != "-q" ] ; then
echo ""
echo "Setting up Ansible to run out of checkout..."
echo ""
echo "PATH=$PATH"
echo "PYTHONPATH=$PYTHONPATH"
echo "MANPATH=$MANPATH"
echo ""
echo "Remember, you may wish to specify your host file with -i"
echo ""
echo "Done!"
echo ""
# Do the work in a function so we don't repeat ourselves later
gen_egg_info()
{
if [ -e "$PREFIX_PYTHONPATH/ansible.egg-info" ] ; then
rm -r "$PREFIX_PYTHONPATH/ansible.egg-info"
fi
python setup.py egg_info
}
if [ "$ANSIBLE_HOME" != "$PWD" ] ; then
current_dir="$PWD"
else
current_dir="$ANSIBLE_HOME"
fi
(
cd "$ANSIBLE_HOME"
if [ "$verbosity" = silent ] ; then
gen_egg_info > /dev/null 2>&1
else
gen_egg_info
fi
cd "$current_dir"
)
if [ "$verbosity" != silent ] ; then
cat <<- EOF
Setting up Ansible to run out of checkout...
PATH=$PATH
PYTHONPATH=$PYTHONPATH
MANPATH=$MANPATH
Remember, you may wish to specify your host file with -i
Done!
EOF
fi

View File

@@ -36,6 +36,16 @@ end
set -gx ANSIBLE_LIBRARY $ANSIBLE_HOME/library
# Generate egg_info so that pkg_resources works
pushd $ANSIBLE_HOME
python setup.py egg_info
if test -e $PREFIX_PYTHONPATH/ansible*.egg-info
rm -r $PREFIX_PYTHONPATH/ansible*.egg-info
end
mv ansible*egg-info $PREFIX_PYTHONPATH
popd
if set -q argv
switch $argv
case '-q' '--quiet'

View File

@@ -31,17 +31,18 @@ import time
import datetime
import subprocess
import cgi
import warnings
from jinja2 import Environment, FileSystemLoader
import ansible.utils
import ansible.utils.module_docs as module_docs
from ansible.utils import module_docs
from ansible.utils.vars import merge_hash
#####################################################################################
# constants and paths
# if a module is added in a version of Ansible older than this, don't print the version added information
# in the module documentation because everyone is assumed to be running something newer than this already.
TO_OLD_TO_BE_NOTABLE = 1.0
TO_OLD_TO_BE_NOTABLE = 1.3
# Get parent directory of the directory this script lives in
MODULEDIR=os.path.abspath(os.path.join(
@@ -59,6 +60,8 @@ _MODULE = re.compile(r"M\(([^)]+)\)")
_URL = re.compile(r"U\(([^)]+)\)")
_CONST = re.compile(r"C\(([^)]+)\)")
DEPRECATED = " (D)"
NOTCORE = " (E)"
#####################################################################################
def rst_ify(text):
@@ -66,7 +69,7 @@ def rst_ify(text):
t = _ITALIC.sub(r'*' + r"\1" + r"*", text)
t = _BOLD.sub(r'**' + r"\1" + r"**", t)
t = _MODULE.sub(r'``' + r"\1" + r"``", t)
t = _MODULE.sub(r':ref:`' + r"\1 <\1>" + r"`", t)
t = _URL.sub(r"\1", t)
t = _CONST.sub(r'``' + r"\1" + r"``", t)
@@ -118,28 +121,53 @@ def write_data(text, options, outputname, module):
#####################################################################################
def list_modules(module_dir):
def list_modules(module_dir, depth=0):
''' returns a hash of categories, each category being a hash of module names to file paths '''
categories = dict(all=dict())
files = glob.glob("%s/*/*" % module_dir)
for d in files:
if os.path.isdir(d):
files2 = glob.glob("%s/*" % d)
for f in files2:
categories = dict(all=dict(),_aliases=dict())
if depth <= 3: # limit # of subdirs
if not f.endswith(".py") or f.endswith('__init__.py'):
files = glob.glob("%s/*" % module_dir)
for d in files:
category = os.path.splitext(os.path.basename(d))[0]
if os.path.isdir(d):
res = list_modules(d, depth + 1)
for key in res.keys():
if key in categories:
categories[key] = merge_hash(categories[key], res[key])
res.pop(key, None)
if depth < 2:
categories.update(res)
else:
category = module_dir.split("/")[-1]
if not category in categories:
categories[category] = res
else:
categories[category].update(res)
else:
module = category
category = os.path.basename(module_dir)
if not d.endswith(".py") or d.endswith('__init__.py'):
# windows powershell modules have documentation stubs in python docstring
# format (they are not executed) so skip the ps1 format files
continue
elif module.startswith("_") and os.path.islink(d):
source = os.path.splitext(os.path.basename(os.path.realpath(d)))[0]
module = module.replace("_","",1)
if not d in categories['_aliases']:
categories['_aliases'][source] = [module]
else:
categories['_aliases'][source].update(module)
continue
tokens = f.split("/")
module = tokens[-1].replace(".py","")
category = tokens[-2]
if not category in categories:
categories[category] = {}
categories[category][module] = f
categories['all'][module] = f
categories[category][module] = d
categories['all'][module] = d
return categories
#####################################################################################
@@ -187,34 +215,60 @@ def jinja2_environment(template_dir, typ):
return env, template, outputname
#####################################################################################
def too_old(added):
if not added:
return False
try:
added_tokens = str(added).split(".")
readded = added_tokens[0] + "." + added_tokens[1]
added_float = float(readded)
except ValueError as e:
warnings.warn("Could not parse %s: %s" % (added, str(e)))
return False
return (added_float < TO_OLD_TO_BE_NOTABLE)
def process_module(module, options, env, template, outputname, module_map):
def process_module(module, options, env, template, outputname, module_map, aliases):
fname = module_map[module]
if isinstance(fname, dict):
return "SKIPPED"
basename = os.path.basename(fname)
deprecated = False
# ignore files with extensions
if not basename.endswith(".py"):
return
elif module.startswith("_"):
if os.path.islink(fname):
return # ignore, its an alias
deprecated = True
module = module.replace("_","",1)
print "rendering: %s" % module
fname = module_map[module]
# ignore files with extensions
if not os.path.basename(fname).endswith(".py"):
return
# use ansible core library to parse out doc metadata YAML and plaintext examples
doc, examples = ansible.utils.module_docs.get_docstring(fname, verbose=options.verbose)
doc, examples, returndocs = module_docs.get_docstring(fname, verbose=options.verbose)
# crash if module is missing documentation and not explicitly hidden from docs index
if doc is None and module not in ansible.utils.module_docs.BLACKLIST_MODULES:
sys.stderr.write("*** ERROR: CORE MODULE MISSING DOCUMENTATION: %s, %s ***\n" % (fname, module))
sys.exit(1)
if doc is None:
return "SKIPPED"
if module in module_docs.BLACKLIST_MODULES:
return "SKIPPED"
else:
sys.stderr.write("*** ERROR: MODULE MISSING DOCUMENTATION: %s, %s ***\n" % (fname, module))
sys.exit(1)
if deprecated and 'deprecated' not in doc:
sys.stderr.write("*** ERROR: DEPRECATED MODULE MISSING 'deprecated' DOCUMENTATION: %s, %s ***\n" % (fname, module))
sys.exit(1)
if "/core/" in fname:
doc['core'] = True
else:
doc['core'] = False
if module in aliases:
doc['aliases'] = aliases[module]
all_keys = []
@@ -229,45 +283,88 @@ def process_module(module, options, env, template, outputname, module_map):
added = doc['version_added']
# don't show version added information if it's too old to be called out
if added:
added_tokens = str(added).split(".")
added = added_tokens[0] + "." + added_tokens[1]
added_float = float(added)
if added and added_float < TO_OLD_TO_BE_NOTABLE:
del doc['version_added']
if too_old(added):
del doc['version_added']
if 'options' in doc:
for (k,v) in doc['options'].iteritems():
# don't show version added information if it's too old to be called out
if 'version_added' in doc['options'][k] and too_old(doc['options'][k]['version_added']):
del doc['options'][k]['version_added']
all_keys.append(k)
for (k,v) in doc['options'].iteritems():
all_keys.append(k)
all_keys = sorted(all_keys)
doc['option_keys'] = all_keys
doc['option_keys'] = all_keys
doc['filename'] = fname
doc['docuri'] = doc['module'].replace('_', '-')
doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
doc['ansible_version'] = options.ansible_version
doc['plainexamples'] = examples #plain text
if returndocs:
doc['returndocs'] = yaml.safe_load(returndocs)
else:
doc['returndocs'] = None
# here is where we build the table of contents...
text = template.render(doc)
write_data(text, options, outputname, module)
return doc['short_description']
#####################################################################################
def print_modules(module, category_file, deprecated, core, options, env, template, outputname, module_map, aliases):
modstring = module
modname = module
if module in deprecated:
modstring = modstring + DEPRECATED
modname = "_" + module
elif module not in core:
modstring = modstring + NOTCORE
result = process_module(modname, options, env, template, outputname, module_map, aliases)
if result != "SKIPPED":
category_file.write(" %s - %s <%s_module>\n" % (modstring, result, module))
def process_category(category, categories, options, env, template, outputname):
module_map = categories[category]
aliases = {}
if '_aliases' in categories:
aliases = categories['_aliases']
category_file_path = os.path.join(options.output_dir, "list_of_%s_modules.rst" % category)
category_file = open(category_file_path, "w")
print "*** recording category %s in %s ***" % (category, category_file_path)
# TODO: start a new category file
# start a new category file
category = category.replace("_"," ")
category = category.title()
modules = module_map.keys()
modules = []
deprecated = []
core = []
for module in module_map.keys():
if isinstance(module_map[module], dict):
for mod in module_map[module].keys():
if mod.startswith("_"):
mod = mod.replace("_","",1)
deprecated.append(mod)
elif '/core/' in module_map[module][mod]:
core.append(mod)
else:
if module.startswith("_"):
module = module.replace("_","",1)
deprecated.append(module)
elif '/core/' in module_map[module]:
core.append(module)
modules.append(module)
modules.sort()
category_header = "%s Modules" % (category.title())
@@ -277,17 +374,34 @@ def process_category(category, categories, options, env, template, outputname):
%s
%s
.. toctree::
:maxdepth: 1
.. toctree:: :maxdepth: 1
""" % (category_header, underscores))
sections = []
for module in modules:
result = process_module(module, options, env, template, outputname, module_map)
if result != "SKIPPED":
category_file.write(" %s_module\n" % module)
if module in module_map and isinstance(module_map[module], dict):
sections.append(module)
continue
else:
print_modules(module, category_file, deprecated, core, options, env, template, outputname, module_map, aliases)
sections.sort()
for section in sections:
category_file.write("\n%s\n%s\n\n" % (section.replace("_"," ").title(),'-' * len(section)))
category_file.write(".. toctree:: :maxdepth: 1\n\n")
section_modules = module_map[section].keys()
section_modules.sort()
#for module in module_map[section]:
for module in section_modules:
print_modules(module, category_file, deprecated, core, options, env, template, outputname, module_map[section], aliases)
category_file.write("""\n\n
.. note::
- %s: This marks a module as deprecated, which means a module is kept for backwards compatibility but usage is discouraged. The module documentation details page may explain more about this rationale.
- %s: This marks a module as 'extras', which means it ships with ansible but may be a newer module and possibly (but not necessarily) less actively maintained than 'core' modules.
- Tickets filed on modules are filed to different repos than those on the main open source project. Core module tickets should be filed at `ansible/ansible-modules-core on GitHub <http://github.com/ansible/ansible-modules-core>`_, extras tickets to `ansible/ansible-modules-extras on GitHub <http://github.com/ansible/ansible-modules-extras>`_
""" % (DEPRECATED, NOTCORE))
category_file.close()
# TODO: end a new category file
@@ -332,6 +446,8 @@ def main():
category_list_file.write(" :maxdepth: 1\n\n")
for category in category_names:
if category.startswith("_"):
continue
category_list_file.write(" list_of_%s_modules\n" % category)
process_category(category, categories, options, env, template, outputname)

View File

@@ -10,6 +10,11 @@
@{ title }@
@{ '+' * title_len }@
{% if version_added is defined -%}
.. versionadded:: @{ version_added }@
{% endif %}
.. contents::
:local:
:depth: 1
@@ -21,17 +26,34 @@
#
--------------------------------------------#}
{% if deprecated is defined -%}
DEPRECATED
----------
@{ deprecated }@
{% endif %}
Synopsis
--------
{% if version_added is defined -%}
.. versionadded:: @{ version_added }@
{% endif %}
{% for desc in description -%}
@{ desc | convert_symbols_to_format }@
{% endfor %}
{% if aliases is defined -%}
Aliases: @{ ','.join(aliases) }@
{% endif %}
{% if requirements %}
Requirements
------------
{% for req in requirements %}
* @{ req | convert_symbols_to_format }@
{% endfor %}
{% endif %}
{% if options -%}
Options
-------
@@ -49,7 +71,7 @@ Options
{% for k in option_keys %}
{% set v = options[k] %}
<tr>
<td>@{ k }@</td>
<td>@{ k }@<br/><div style="font-size: small;">{% if v['version_added'] %} (added in @{v['version_added']}@){% endif %}</div></td>
<td>{% if v.get('required', False) %}yes{% else %}no{% endif %}</td>
<td>{% if v['default'] %}@{ v['default'] }@{% endif %}</td>
{% if v.get('type', 'not_bool') == 'bool' %}
@@ -57,82 +79,112 @@ Options
{% else %}
<td><ul>{% for choice in v.get('choices',[]) -%}<li>@{ choice }@</li>{% endfor -%}</ul></td>
{% endif %}
<td>{% for desc in v.description -%}@{ desc | html_ify }@{% endfor -%}{% if v['version_added'] %} (added in Ansible @{v['version_added']}@){% endif %}</td>
</tr>
<td>{% for desc in v.description -%}<div>@{ desc | html_ify }@</div>{% endfor -%} {% if 'aliases' in v and v.aliases -%}</br>
<div style="font-size: small;">aliases: @{ v.aliases|join(', ') }@<div>{%- endif %}</td></tr>
{% endfor %}
</table>
</br>
{% endif %}
{% if requirements %}
{% for req in requirements %}
.. note:: Requires @{ req | convert_symbols_to_format }@
{% endfor %}
{% endif %}
{% if examples or plainexamples %}
{% if examples or plainexamples -%}
Examples
--------
.. raw:: html
::
{% for example in examples %}
{% if example['description'] %}<p>@{ example['description'] | html_ify }@</p>{% endif %}
<p>
<pre>
{% if example['description'] %}@{ example['description'] | indent(4, True) }@{% endif %}
@{ example['code'] | escape | indent(4, True) }@
</pre>
</p>
{% endfor %}
<br/>
{% if plainexamples %}
::
@{ plainexamples | indent(4, True) }@
{% endif %}
{% if plainexamples %}@{ plainexamples | indent(4, True) }@{% endif %}
{% endif %}
{% if notes %}
{% if returndocs -%}
Return Values
-------------
Common return values are documented here :doc:`common_return_values`, the following are the fields unique to this module:
.. raw:: html
<table border=1 cellpadding=4>
<tr>
<th class="head">name</th>
<th class="head">description</th>
<th class="head">returned</th>
<th class="head">type</th>
<th class="head">sample</th>
</tr>
{% for entry in returndocs %}
<tr>
<td> @{ entry }@ </td>
<td> @{ returndocs[entry].description }@ </td>
<td align=center> @{ returndocs[entry].returned }@ </td>
<td align=center> @{ returndocs[entry].type }@ </td>
<td align=center> @{ returndocs[entry].sample}@ </td>
</tr>
{% if returndocs[entry].type == 'dictionary' %}
<tr><td>contains: </td>
<td colspan=4>
<table border=1 cellpadding=2>
<tr>
<th class="head">name</th>
<th class="head">description</th>
<th class="head">returned</th>
<th class="head">type</th>
<th class="head">sample</th>
</tr>
{% for sub in returndocs[entry].contains %}
<tr>
<td> @{ sub }@ </td>
<td> @{ returndocs[entry].contains[sub].description }@ </td>
<td align=center> @{ returndocs[entry].contains[sub].returned }@ </td>
<td align=center> @{ returndocs[entry].contains[sub].type }@ </td>
<td align=center> @{ returndocs[entry].contains[sub].sample}@ </td>
</tr>
{% endfor %}
</table>
</td></tr>
{% endif %}
{% endfor %}
</table>
</br></br>
{% endif %}
{% if notes -%}
Notes
-----
{% for note in notes %}
.. note:: @{ note | convert_symbols_to_format }@
{% endfor %}
{% endif %}
{% if core %}
{% if not deprecated %}
{% if core %}
This is a Core Module
---------------------
This source of this module is hosted on GitHub in the `ansible-modules-core <http://github.com/ansible/ansible-modules-core>`_ repo.
If you believe you have found a bug in this module, and are already running the latest stable or development version of Ansible, first look in the `issue tracker at github.com/ansible/ansible-modules-core <http://github.com/ansible/ansible-modules-core>`_ to see if a bug has already been filed. If not, we would be grateful if you would file one.
For more information on what this means please read :doc:`modules_core`
Should you have a question rather than a bug report, inquries are welcome on the `ansible-project google group <https://groups.google.com/forum/#!forum/ansible-project>`_ or on Ansible's "#ansible" channel, located on irc.freenode.net. Development oriented topics should instead use the similar `ansible-devel google group <https://groups.google.com/forum/#!forum/ansible-project>`_.
Documentation updates for this module can also be edited directly by submitting a pull request to the module source code, just look for the "DOCUMENTATION" block in the source tree.
This is a "core" ansible module, which means it will receive slightly higher priority for all requests than those in the "extras" repos.
{% else %}
{% else %}
This is an Extras Module
------------------------
This source of this module is hosted on GitHub in the `ansible-modules-extras <http://github.com/ansible/ansible-modules-extras>`_ repo.
If you believe you have found a bug in this module, and are already running the latest stable or development version of Ansible, first look in the `issue tracker at github.com/ansible/ansible-modules-extras <http://github.com/ansible/ansible-modules-extras>`_ to see if a bug has already been filed. If not, we would be grateful if you would file one.
Should you have a question rather than a bug report, inquries are welcome on the `ansible-project google group <https://groups.google.com/forum/#!forum/ansible-project>` or on Ansible's "#ansible" channel, located on irc.freenode.net. Development oriented topics should instead use the similar `ansible-devel google group <https://groups.google.com/forum/#!forum/ansible-project>`_.
Documentation updates for this module can also be edited directly by submitting a pull request to the module source code, just look for the "DOCUMENTATION" block in the source tree.
Note that this module is designated a "extras" module. Non-core modules are still fully usable, but may receive slightly lower response rates for issues and pull requests.
Popular "extras" modules may be promoted to core modules over time.
For more information on what this means please read :doc:`modules_extra`
{% endif %}
{% endif %}
For help in developing on modules, should you be so inclined, please read :doc:`community`, :doc:`developing_test_pr` and :doc:`developing_modules`.

View File

@@ -26,7 +26,8 @@
# test-module -m ../library/commands/command -a "/bin/sleep 3"
# test-module -m ../library/system/service -a "name=httpd ensure=restarted"
# test-module -m ../library/system/service -a "name=httpd ensure=restarted" --debugger /usr/bin/pdb
# test-modulr -m ../library/file/lineinfile -a "dest=/etc/exports line='/srv/home hostname1(rw,sync)'" --check
# test-module -m ../library/file/lineinfile -a "dest=/etc/exports line='/srv/home hostname1(rw,sync)'" --check
# test-module -m ../library/commands/command -a "echo hello" -n -o "test_hello"
import sys
import base64
@@ -34,8 +35,11 @@ import os
import subprocess
import traceback
import optparse
import ansible.utils as utils
import ansible.module_common as module_common
import ansible.utils.vars as utils_vars
from ansible.parsing import DataLoader
from ansible.parsing.utils.jsonify import jsonify
from ansible.parsing.splitter import parse_kv
import ansible.executor.module_common as module_common
import ansible.constants as C
try:
@@ -58,10 +62,16 @@ def parse():
parser.add_option('-D', '--debugger', dest='debugger',
help="path to python debugger (e.g. /usr/bin/pdb)")
parser.add_option('-I', '--interpreter', dest='interpreter',
help="path to interpeter to use for this module (e.g. ansible_python_interpreter=/usr/bin/python)",
metavar='INTERPRETER_TYPE=INTERPRETER_PATH')
help="path to interpreter to use for this module (e.g. ansible_python_interpreter=/usr/bin/python)",
metavar='INTERPRETER_TYPE=INTERPRETER_PATH',
default='python={}'.format(sys.executable))
parser.add_option('-c', '--check', dest='check', action='store_true',
help="run the module in check mode")
parser.add_option('-n', '--noexecute', dest='execute', action='store_false',
default=True, help="do not run the resulting module")
parser.add_option('-o', '--output', dest='filename',
help="Filename for resulting module",
default="~/.ansible_module_generated")
options, args = parser.parse_args()
if not options.module_path:
parser.print_help()
@@ -74,37 +84,38 @@ def write_argsfile(argstring, json=False):
argspath = os.path.expanduser("~/.ansible_test_module_arguments")
argsfile = open(argspath, 'w')
if json:
args = utils.parse_kv(argstring)
argstring = utils.jsonify(args)
args = parse_kv(argstring)
argstring = jsonify(args)
argsfile.write(argstring)
argsfile.close()
return argspath
def boilerplate_module(modfile, args, interpreter, check):
def boilerplate_module(modfile, args, interpreter, check, destfile):
""" simulate what ansible does with new style modules """
#module_fh = open(modfile)
#module_data = module_fh.read()
#module_fh.close()
replacer = module_common.ModuleReplacer()
#replacer = module_common.ModuleReplacer()
loader = DataLoader()
#included_boilerplate = module_data.find(module_common.REPLACER) != -1 or module_data.find("import ansible.module_utils") != -1
complex_args = {}
if args.startswith("@"):
# Argument is a YAML file (JSON is a subset of YAML)
complex_args = utils.combine_vars(complex_args, utils.parse_yaml_from_file(args[1:]))
complex_args = utils_vars.combine_vars(complex_args, loader.load_from_file(args[1:]))
args=''
elif args.startswith("{"):
# Argument is a YAML document (not a file)
complex_args = utils.combine_vars(complex_args, utils.parse_yaml(args))
complex_args = utils_vars.combine_vars(complex_args, loader.load(args))
args=''
inject = {}
if interpreter:
if '=' not in interpreter:
print 'interpeter must by in the form of ansible_python_interpreter=/usr/bin/python'
print 'interpreter must by in the form of ansible_python_interpreter=/usr/bin/python'
sys.exit(1)
interpreter_type, interpreter_path = interpreter.split('=')
if not interpreter_type.startswith('ansible_'):
@@ -116,14 +127,14 @@ def boilerplate_module(modfile, args, interpreter, check):
if check:
complex_args['CHECKMODE'] = True
(module_data, module_style, shebang) = replacer.modify_module(
(module_data, module_style, shebang) = module_common.modify_module(
modfile,
complex_args,
args,
inject
)
modfile2_path = os.path.expanduser("~/.ansible_module_generated")
modfile2_path = os.path.expanduser(destfile)
print "* including generated source, if any, saving to: %s" % modfile2_path
print "* this may offset any line numbers in tracebacks/debuggers!"
modfile2 = open(modfile2_path, 'w')
@@ -150,7 +161,7 @@ def runtest( modfile, argspath):
print "RAW OUTPUT"
print out
print err
results = utils.parse_json(out)
results = json.loads(out)
except:
print "***********************************"
print "INVALID OUTPUT FORMAT"
@@ -160,7 +171,7 @@ def runtest( modfile, argspath):
print "***********************************"
print "PARSED OUTPUT"
print utils.jsonify(results,format=True)
print jsonify(results,format=True)
def rundebug(debugger, modfile, argspath):
"""Run interactively with console debugger."""
@@ -173,9 +184,9 @@ def rundebug(debugger, modfile, argspath):
def main():
options, args = parse()
(modfile, module_style) = boilerplate_module(options.module_path, options.module_args, options.interpreter, options.check)
(modfile, module_style) = boilerplate_module(options.module_path, options.module_args, options.interpreter, options.check, options.filename)
argspath=None
argspath = None
if module_style != 'new':
if module_style == 'non_native_want_json':
argspath = write_argsfile(options.module_args, json=True)
@@ -183,10 +194,11 @@ def main():
argspath = write_argsfile(options.module_args, json=False)
else:
raise Exception("internal error, unexpected module style: %s" % module_style)
if options.debugger:
rundebug(options.debugger, modfile, argspath)
else:
runtest(modfile, argspath)
if options.execute:
if options.debugger:
rundebug(options.debugger, modfile, argspath)
else:
runtest(modfile, argspath)
if __name__ == "__main__":
main()

3
hacking/update.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
git pull --rebase
git submodule update --init --recursive