Ansible - 处理自定义模块中的意外 STDOUT
Ansible - dealing with unexpected STDOUT in custom module
我编写了一个包装 Python 库的自定义模块。我定义 result
dict 如下:
result = dict(
changed=False,
original_message='Running DBSCONTROL',
message=''
)
稍后在代码中,我将对库的调用包装到 try/except
中:
try:
dbsc = DbsControl(
module.params.get('user'),
module.params.get('host'),
module.params.get('script')
)
dbsc.runme()
result['message'] = 'DBSCONTROL_SUCCESSFULL'
module.exit_json(**result)
except Exception as ex:
result['message'] = str(ex)
module.fail_json(msg='Failed DBSCONTROL execution', **result)
我在模块中的任何地方都没有单个 print
语句,我的 lib 输出日志到一个文件中。
最后我称这个 Ansible 角色
- name: Run dbscontrol utility
dbscontrol:
user: "{{ hostvars[groups['dbs_server'][0]]['ansible_user'] }}"
host: "{{ groups['dbs_server'][0] }}"
script: "dbscontrol_config.yml"
register: result
- debug:
msg: "{{ result }}"
从我的库中的最后一条记录器消息中,我可以清楚地看到 运行 已成功完成,但是我的模块最终失败了,记录器消息以
开头的大量输出
MSG:
MODULE FAILURE
See stdout/stderr for the exact error
奇怪的是,我看到 result
嵌入到输出的 MODULE_STDOUT 部分。事实上,这是 MODULE_STDERR 开始前的最后一节
MODULE_STDOUT 和 MODULE_STDERR 都包含来自 lib 的相同日志消息,唯一的区别是 result
相关行:
2020-01-23 13:40:52,070 - ttautils.dbscontrol - INFO - DBS control run is complete, exiting
{"changed": false, "original_message": "Running DBSCONTROL", "message": "DBSCONTROL_SUCCESSFULL",
"invocation": {"module_args": {"user": "root", "host": "fiesta1.td.teradata.com", "script":
"dbscontrol_config.yml", "dbc_user": "dbc", "dbc_pwd": "dbc", "logfile": "dbscntl_2020-01-23-13-38-15.log",
"loglevel": "DEBUG", "validate": "False", "config": "user_config/common", "locale": "TPG_6700C",
"timeout": "7200", "disable_local_overrides": false, "params": "user_config/user.yml"}},
"warnings": ["The value False (type bool) in a string field was converted to 'False' (type string).
If this does not look like what you expect, quote the entire value to ensure it does not change."]}
问题是模块总是以 "failed" 结束,即使我知道我的代码 运行 成功,剧本也会终止。
2 天后
好的,我现在知道问题所在了。这是由于我正在将输出包装到 STDOUT/STDERR 的库,因为它在内部使用子进程。当 Ansible 尝试解析 STDOUT 时,由于 STDOUT 中所有额外的非 JSON 输出,它失败了 in this method。
如何处理这种情况?我怎么可能 gua运行tee 我的自定义模块有一个只有 JSON 格式输出的原始 STDOUT?我试图做 sys.stdout.flush()
但无济于事。
这实际上使编写自定义模块变得毫无用处。请 Ansible 专家,有什么提示吗?
所以这个问题的答案很简单:当你调用 exit_json
或 fail_json
时,你不能让 sys.stdout
有任何类型的输出。原因也很简单:你的代码是运行后结果被this Ansible code处理了。哪个解析 res.get('stdout', u'')
如果有任何解析错误,那么你最终会得到我在问题中提到的大量 STDOUT 转储。
解决办法没那么简单。在调用模块退出方法之前,我尝试了各种技巧来清空 STDOUT,但它并没有真正起作用。因此,由于我可以完全控制我调用的内容,我只是将我的日志记录更改为基于我调用的库的临时文件,并做了一些其他事情来确保我没有以任何方式使用 sys.stdout
。这真的很愚蠢,我希望有人能告诉我更好的方法
我编写了一个包装 Python 库的自定义模块。我定义 result
dict 如下:
result = dict(
changed=False,
original_message='Running DBSCONTROL',
message=''
)
稍后在代码中,我将对库的调用包装到 try/except
中:
try:
dbsc = DbsControl(
module.params.get('user'),
module.params.get('host'),
module.params.get('script')
)
dbsc.runme()
result['message'] = 'DBSCONTROL_SUCCESSFULL'
module.exit_json(**result)
except Exception as ex:
result['message'] = str(ex)
module.fail_json(msg='Failed DBSCONTROL execution', **result)
我在模块中的任何地方都没有单个 print
语句,我的 lib 输出日志到一个文件中。
最后我称这个 Ansible 角色
- name: Run dbscontrol utility
dbscontrol:
user: "{{ hostvars[groups['dbs_server'][0]]['ansible_user'] }}"
host: "{{ groups['dbs_server'][0] }}"
script: "dbscontrol_config.yml"
register: result
- debug:
msg: "{{ result }}"
从我的库中的最后一条记录器消息中,我可以清楚地看到 运行 已成功完成,但是我的模块最终失败了,记录器消息以
开头的大量输出MSG:
MODULE FAILURE
See stdout/stderr for the exact error
奇怪的是,我看到 result
嵌入到输出的 MODULE_STDOUT 部分。事实上,这是 MODULE_STDERR 开始前的最后一节
MODULE_STDOUT 和 MODULE_STDERR 都包含来自 lib 的相同日志消息,唯一的区别是 result
相关行:
2020-01-23 13:40:52,070 - ttautils.dbscontrol - INFO - DBS control run is complete, exiting
{"changed": false, "original_message": "Running DBSCONTROL", "message": "DBSCONTROL_SUCCESSFULL",
"invocation": {"module_args": {"user": "root", "host": "fiesta1.td.teradata.com", "script":
"dbscontrol_config.yml", "dbc_user": "dbc", "dbc_pwd": "dbc", "logfile": "dbscntl_2020-01-23-13-38-15.log",
"loglevel": "DEBUG", "validate": "False", "config": "user_config/common", "locale": "TPG_6700C",
"timeout": "7200", "disable_local_overrides": false, "params": "user_config/user.yml"}},
"warnings": ["The value False (type bool) in a string field was converted to 'False' (type string).
If this does not look like what you expect, quote the entire value to ensure it does not change."]}
问题是模块总是以 "failed" 结束,即使我知道我的代码 运行 成功,剧本也会终止。
2 天后
好的,我现在知道问题所在了。这是由于我正在将输出包装到 STDOUT/STDERR 的库,因为它在内部使用子进程。当 Ansible 尝试解析 STDOUT 时,由于 STDOUT 中所有额外的非 JSON 输出,它失败了 in this method。
如何处理这种情况?我怎么可能 gua运行tee 我的自定义模块有一个只有 JSON 格式输出的原始 STDOUT?我试图做 sys.stdout.flush()
但无济于事。
这实际上使编写自定义模块变得毫无用处。请 Ansible 专家,有什么提示吗?
所以这个问题的答案很简单:当你调用 exit_json
或 fail_json
时,你不能让 sys.stdout
有任何类型的输出。原因也很简单:你的代码是运行后结果被this Ansible code处理了。哪个解析 res.get('stdout', u'')
如果有任何解析错误,那么你最终会得到我在问题中提到的大量 STDOUT 转储。
解决办法没那么简单。在调用模块退出方法之前,我尝试了各种技巧来清空 STDOUT,但它并没有真正起作用。因此,由于我可以完全控制我调用的内容,我只是将我的日志记录更改为基于我调用的库的临时文件,并做了一些其他事情来确保我没有以任何方式使用 sys.stdout
。这真的很愚蠢,我希望有人能告诉我更好的方法