diff --git a/hacking/test-module b/hacking/test-module index 328071059d..0301dd1452 100755 --- a/hacking/test-module +++ b/hacking/test-module @@ -29,7 +29,6 @@ # 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 base64 import optparse import os import subprocess @@ -49,6 +48,7 @@ try: except ImportError: import simplejson as json + def parse(): """parse command line @@ -61,12 +61,11 @@ def parse(): help="REQUIRED: full path of module source to execute") parser.add_option('-a', '--args', dest='module_args', default="", help="module argument string") - parser.add_option('-D', '--debugger', dest='debugger', + 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 interpreter to use for this module (e.g. ansible_python_interpreter=/usr/bin/python)", - metavar='INTERPRETER_TYPE=INTERPRETER_PATH', - default='python={0}'.format(sys.executable)) + metavar='INTERPRETER_TYPE=INTERPRETER_PATH') 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', @@ -81,6 +80,7 @@ def parse(): else: return options, args + def write_argsfile(argstring, json=False): """ Write args to a file for old-style module's use. """ argspath = os.path.expanduser("~/.ansible_test_module_arguments") @@ -92,17 +92,33 @@ def write_argsfile(argstring, json=False): argsfile.close() return argspath -def boilerplate_module(modfile, args, interpreter, check, destfile): + +def get_interpreters(interpreter): + result = dict() + if interpreter: + if '=' not in interpreter: + 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_'): + interpreter_type = 'ansible_%s' % interpreter_type + if not interpreter_type.endswith('_interpreter'): + interpreter_type = '%s_interpreter' % interpreter_type + result[interpreter_type] = interpreter_path + return result + + +def boilerplate_module(modfile, args, interpreters, check, destfile): """ simulate what ansible does with new style modules """ - #module_fh = open(modfile) - #module_data = module_fh.read() - #module_fh.close() + # 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 + # included_boilerplate = module_data.find(module_common.REPLACER) != -1 or module_data.find("import ansible.module_utils") != -1 complex_args = {} @@ -122,20 +138,10 @@ def boilerplate_module(modfile, args, interpreter, check, destfile): parsed_args = parse_kv(args) complex_args = utils_vars.combine_vars(complex_args, parsed_args) - task_vars = {} - if interpreter: - if '=' not in interpreter: - 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_'): - interpreter_type = 'ansible_%s' % interpreter_type - if not interpreter_type.endswith('_interpreter'): - interpreter_type = '%s_interpreter' % interpreter_type - task_vars[interpreter_type] = interpreter_path + task_vars = interpreters if check: - complex_args['_ansible_check_mode'] = True + complex_args['_ansible_check_mode'] = True modname = os.path.basename(modfile) modname = os.path.splitext(modname)[0] @@ -160,10 +166,17 @@ def boilerplate_module(modfile, args, interpreter, check, destfile): return (modfile2_path, modname, module_style) -def ansiballz_setup(modfile, modname): + +def ansiballz_setup(modfile, modname, interpreters): os.system("chmod +x %s" % modfile) - cmd = subprocess.Popen([modfile, 'explode'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if 'ansible_python_interpreter' in interpreters: + command = [interpreters['ansible_python_interpreter']] + else: + command = [] + command.extend([modfile, 'explode']) + + cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = cmd.communicate() lines = out.splitlines() if len(lines) != 2 or 'Module expanded into' not in lines[0]: @@ -179,16 +192,21 @@ def ansiballz_setup(modfile, modname): print("* ansiballz module detected; extracted module source to: %s" % debug_dir) return modfile, argsfile -def runtest(modfile, argspath, modname, module_style): + +def runtest(modfile, argspath, modname, module_style, interpreters): """Test run a module, piping it's output for reporting.""" if module_style == 'ansiballz': - modfile, argspath = ansiballz_setup(modfile, modname) + modfile, argspath = ansiballz_setup(modfile, modname, interpreters) + if 'ansible_python_interpreter' in interpreters: + invoke = "%s " % interpreters['ansible_python_interpreter'] + else: + invoke = "" os.system("chmod +x %s" % modfile) - invoke = "%s" % (modfile) + invoke = "%s%s" % (invoke, modfile) if argspath is not None: - invoke = "%s %s" % (modfile, argspath) + invoke = "%s %s" % (invoke, argspath) cmd = subprocess.Popen(invoke, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = cmd.communicate() @@ -210,6 +228,7 @@ def runtest(modfile, argspath, modname, module_style): print("PARSED OUTPUT") print(jsonify(results,format=True)) + def rundebug(debugger, modfile, argspath, modname, module_style): """Run interactively with console debugger.""" @@ -221,10 +240,12 @@ def rundebug(debugger, modfile, argspath, modname, module_style): else: subprocess.call("%s %s" % (debugger, modfile), shell=True) + def main(): options, args = parse() - (modfile, modname, module_style) = boilerplate_module(options.module_path, options.module_args, options.interpreter, options.check, options.filename) + interpreters = get_interpreters(options.interpreter) + (modfile, modname, module_style) = boilerplate_module(options.module_path, options.module_args, interpreters, options.check, options.filename) argspath = None if module_style not in ('new', 'ansiballz'): @@ -234,15 +255,15 @@ def main(): argspath = write_argsfile(options.module_args, json=False) else: raise Exception("internal error, unexpected module style: %s" % module_style) + if options.execute: if options.debugger: rundebug(options.debugger, modfile, argspath, modname, module_style) else: - runtest(modfile, argspath, modname, module_style) + runtest(modfile, argspath, modname, module_style, interpreters) if __name__ == "__main__": try: main() finally: shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) -