Ansible开发实战:解决callback中只能识别原生模块名称的问题

(本文基于Ansible 2.7)
近来在开发过程中遇到一个问题:所有基于command模块编写的action plugin在callback中取result._task_fields[‘action’],均被识别为command模块。
这个问题虽然并不影响任务执行,但对后期的数据收集、统计和分析造成了麻烦,无法进行更细致的分类查询。
Ansible 源码解析: shell模块的实现方式Ansible开发实战: 基于command模块的Oracle Listener控制模块(附趟雷过程及样例)这两篇文章中,我们讨论了如何基于command模块开发定制plugin,本文以shell模块的实现方式为例:

lib/ansible/plugins/action/shell.py:

# Copyright: (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.plugins.action import ActionBase
from ansible.utils.vars import merge_hash


class ActionModule(ActionBase):

    def run(self, tmp=None, task_vars=None):
        del tmp  # tmp no longer has any effect

        # Shell module is implemented via command
        self._task.action = 'command'
        self._task.args['_uses_shell'] = True

        command_action = self._shared_loader_obj.action_loader.get('command',
                                                                   task=self._task,
                                                                   connection=self._connection,
                                                                   play_context=self._play_context,
                                                                   loader=self._loader,
                                                                   templar=self._templar,
                                                                   shared_loader_obj=self._shared_loader_obj)
        result = command_action.run(task_vars=task_vars)

        return result

这里run方法最后的返回值result实际上就是callback里的result._result(可以参见lib/ansible/executor/task_executor.py),是字典类型。所以如果仅想将plugin的名字传给callback是很简单的,在run方法返回之前给result增加一个字段即可,例如:

		result['orig_action'] = 'shell'

我们目前采用的即是这个方案,它的好处是不用修改ansible的源码,方便以后的更新。而这样做的缺点是不得不在callback中增加新的逻辑分支,先在result._result中查询这个字段是否存在,再决定是否使用result._taskfields[‘action’],未免显得有些繁冗。

那么为什么我们不直接修改taskfields呢?在task_executor中我们可以看到task_fields的取值是task.dump_attrs()(338行)。ansible在读取task的attributes的时候是做了检查的(有空会写一下这个检查的过程),检查未通过的attribute会被丢弃。

self._task.action = 'command'

这一行我们是不能修改的,毕竟任务的实际执行是通过command模块实现的。

self._task.orig_action = 'command'

如果加入这一行,则任务可以正常运行,但orig_action 并不会被包含在result._task_fields里,被丢掉了。

如果一定想通过_task_fields传这个值,可以修改task的源码来实现(lib/ansible/playbook/task.py),在task类中加入_orig_action的定义:

_orig_action = FieldAttribute(isa='string')

就可以了

2019-05-13:
在允许修改Ansible源码的前提之下,本问题已经有更优的解决办法,详见:
Ansible开发实战:在结果输出Action Plugin的名称

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值