1.为什么会有这篇文章的介绍?
在ansible文档中,有一篇介绍用户自定义模块的文章,链接地址如下:开发模块。但是测试的时候总会出现异常,后面的 *** 作无法继续,所以我看看怎么测试模块。
2.有两种自定义模块。
1> 不传参数的,如下 # ansible -i hosts hostgroup -m ping -k 2> 传递参数的, 如下 # ansible -i hsots hostgroup -m shell -a 'uptime' -kAnsible的文档也给出了两个相应的定制模块的例子。
1> 不传参数的 #!/usr/bin/python import datetime import json date = str(datetime.datetime.now()) print json.dumps({ "time" : date })2>传递的参数
#!/usr/bin/python # import some python modules that we'll use. These are all # available in Python's core import datetime import sys import json import os import shlex # read the argument string from the arguments file args_file = sys.argv[1] args_data = file(args_file).read() # for this module, we're going to do key=value style arguments # this is up to each module to decide what it wants, but all # core modules besides 'command' and 'shell' take key=value # so this is highly recommended arguments = shlex.split(args_data) for arg in arguments: # ignore any arguments without an equals in it if "=" in arg: (key, value) = arg.split("=") # if setting the time, the key 'time' # will contain the value we want to set the time to if key == "time": # now we'll affect the change. Many modules # will strive to be 'idempotent', meaning they # will only make changes when the desired state # expressed to the module does not match # the current state. Look at 'service' # or 'yum' in the main git tree for an example # of how that might look. rc = os.system("date -s \"%s\"" % value) # always handle all possible errors # # when returning a failure, include 'failed' # in the return data, and explain the failure # in 'msg'. Both of these conventions are # required however additional keys and values # can be added. if rc != 0: print json.dumps({ "failed" : True, "msg" : "failed setting the time" }) sys.exit(1) # when things do not fail, we do not # have any restrictions on what kinds of # data are returned, but it's always a # good idea to include whether or not # a change was made, as that will allow # notifiers to be used in playbooks. date = str(datetime.datetime.now()) print json.dumps({ "time" : date, "changed" : True }) sys.exit(0) # if no parameters are sent, the module may or # may not error out, this one will just # return the time date = str(datetime.datetime.now()) print json.dumps({ "time" : date })不管有没有参数,如何在模块写好之后测试自己写的模块是否正确?
Ansible的文档给出了一种检测模块的方法:
测试模块
ansible的源代码检查中有一个有用的测试脚本
3.测试模块
1>没有参数传递的用户定义的模块执行模式
例如,如果脚本名为timetest.py,执行命令如下
#ansible/hacking/test-module-m./timetest.py
* including generated source, if any, saving to: /root/.ansible_module_generated * this may offset any line numbers in tracebacks/debuggers! *********************************** RAW OUTPUT {"time": "2016-04-03 02:09:41.516592"} *********************************** PARSED OUTPUT { "time": "2016-04-03 02:09:41.516592" }2>具有参数传递执行模式的用户定义模块
例如,如果您的脚本名称为timetest.py,传递的参数为time="March1422:10",则执行命令如下
#ansible/hacking/test-module-m./timetest.py-a"time=\"3月14日12:23\""
带参数的此位置的执行失败报告如下
[root@ManagerAnsible sourceCode_tmp]# ansible/hacking/test-module -m ../modules/timetest_params.py -a "time=\"March 14 12:23\"" * including generated source, if any, saving to: /root/.ansible_module_generated * this may offset any line numbers in tracebacks/debuggers! *********************************** RAW OUTPUT Mon Mar 14 12:23:00 UTC 2016 {"changed": true, "time": "2016-03-14 12:23:00.000262"} *********************************** INVALID OUTPUT FORMAT Mon Mar 14 12:23:00 UTC 2016 {"changed": true, "time": "2016-03-14 12:23:00.000262"} Traceback (most recent call last): File "ansible/hacking/test-module", line 167, in runtest results = json.loads(out) File "/usr/local/python27/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/local/python27/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/local/python27/lib/python2.7/json/decoder.py", line 382, in raw_decode raise ValueError("No JSON object could be decoded") ValueError: No JSON object could be decoded从上面的错误可以追溯到json.loads对象中167行ansible/hacking/test-module脚本失败。
try: print("***********************************") print("RAW OUTPUT") print(out) print(err) results = json.loads(out) # 第167行 except: print("***********************************") print("INVALID OUTPUT FORMAT") print(out) traceback.print_exc() sys.exit(1) print("***********************************") print("PARSED OUTPUT") print(jsonify(results,format=True))至于为什么会出现这个问题,文章后面会有解决方法。......
首先看timetest.py文件(有几行注释比较多)
这篇课文的前两行我不太明白
args_file=sys.argv[1]
args_data=file(args_file)。阅读()
# 接受一个参数 args_file = sys.argv[1] # 打开这个参数 file <<>> open args_data = file(args_file).read() //开始纳闷了开始纳闷了开始纳闷了然后跟踪这个文件ansible/hacking/test-module。
有兴趣在test-module中加入中文评论的朋友可以参考文末已经上传的附件。
解决了两个问题:
问题1:
安全/黑客/测试模块
有以下功能
Parse#接受命令行参数。
Write_argsfile#将命令行传递的参数写入指定的文件。
Boilerplate_module#写入。/timetest.py文件添加到命令行上默认指定的模块文件中。
Runtest#执行foot并打开参数文件。
总结
Boilerplate_module这个函数:将用户定义的模块写入文件~/。ansible_module_generated。
Write_argsfile此函数:将用户传递的参数写入文件~/。ansible_test_module_arguments。
运行这个函数:执行脚本和传递的参数~/。ansible_module_generated~/。ansible_测试_模块_参数
问题2:
修改文档中的timetest.py代码。
修改前 rc = os.system("date -s \"%s\"" % value) 修改后 import commands rc, output = commands.getstatusoutput('date -s \"%s\"' % value)其实有两件事让我想到了这里的原因:
1.原因:
首先,看一下timetest.py代码的摘录。
rc = os.system("date -s \"%s\"" % value) if rc != 0:rc得到的是os.system的命令执行结果还是os.system的返回值?
我想你能理解第二行的if语句。
原因二:
ansible/hacking/测试模块文件
def runtest( modfile, argspath): """Test run a module, piping it's output for reporting.""" os.system("chmod +x %s" % modfile) invoke = "%s" % (modfile) if argspath is not None: invoke = "%s %s" % (modfile, argspath) cmd = subprocess.Popen(invoke, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = cmd.communicate() try: print("***********************************") print("RAW OUTPUT") print(out) print(err) results = json.loads(out) except: print("***********************************") print("INVALID OUTPUT FORMAT") print(out) traceback.print_exc() sys.exit(1) print("***********************************") print("PARSED OUTPUT") print(jsonify(results,format=True))这个函数的正确返回结果必须是json格式,timetest.py文件有两个打印;第一次打印是os.system的执行结果;第二个是printjson.dumps的结果,显然这是两行打印不可能是json。
那我举个例子来说明。
# 对timetest.py简写成如下格式 import os, datetime, json os.system('date -s %s' % 3) date = str(datetime.datetime.now()) print json.dumps({ "time" : date, "changed" : True }) # 那么test-module中的out就相当于上面执行结果的相加 "Mon Mar 14 03:00:00 UTC 2016" + "{"changed": true, "time": "2016-03-14 03:00:00.013835"}" 以上这种格式你是无法进行json.loads成json对象的 所以也就是报错的原因.文章的最后是如何使用用户自定义模块。第一部分介绍如何测试模块,下一部分是如何正确使用自定义模块。
(1)通过ansible-help|grepmodule
用-M指定自定义模块的路径.
(2)由ANSIBLE_LIBRARY变量指定。
<<好在我的Google里很多文章都没有用前两种方式解决。如果有朋友有解决的版本,请告诉我>:>
③我用了最后一个笨办法:
当前python版本为源码安装方式 2.7版本 python的安装路径为/usr/local/python27 python模块包路径为/usr/local/python27/lib/python2.7/site-packages/ansible/modules 其中有core(核心包)和extras(扩展包)两个目录 那么自定义模块 应该属于扩展包吧 于是做如下 *** 作 # cd /usr/local/python27/lib/python2.7/site-packages/ansible/modules/extras # mkdir zhengys # cp ~/demo/ansible/modules/* ./ 也就是把自定义的模块都放置与extras/zhengys目录下 就可以使用了下载地址:http://pan.baidu.com/s/1kVQwgej
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)