使用' set_fact'获取事实集的价值在回调插件中

时间:2017-04-14 17:17:04

标签: python callback ansible

Ansible 2.3

我有一个回调插件,可在播放完成后通知外部服务。在播放期间,此回调插件收集不同的信息,如播放变量和错误消息,这些信息随HTTP请求一起发送。例如:

{
    "status": 1, 
    "activity": 270,
    "error": "Task xyz failed with message: failure message",
    "files": [ "a.txt", "b.cfg" ]
}

其中一些信息来自播放过程中设置的变量,它可能与该播放相关:文件路径,更改资源列表等。

现在我正在根据任务名称收集我需要的东西特别难看:

def v2_runner_on_ok(self, result):

    if result._task.action == 'archive':
        if result._task.name == 'Create archive foo':
            self.body['path'] = result._result['path']

    if result._task.action == 'ec2':
        if result._task.name == 'Start instance bar':
            self.body['ec2_id'] = result._result['id']

   # do it for every task which generates "interesting" info

显然,如果任务名称发生变化,这不会缩放和中断。

为了保持通用性,我一直在考虑就事实名称达成一致,比如add_to_body,只要它存在就会添加到body字典中。我喜欢这种方法,因为在游戏过程中注册几个变量特别容易,并且在游戏结束时使用它们来组合事实。例如:

---

- name: Demo play
  hosts: localhost
  gather_facts: False

  tasks:

    - name: Create temporary file 1
      tempfile:
        path: '/tmp'
      register: reg_tmp_1

    - name: Create temporary file 2
      tempfile:
        path: '/tmp'
      register: reg_tmp_2

    - name: Set add_to_body fact
      set_fact:
        add_to_body: "{{ { 'reg_tmp_1': reg_tmp_1.path,
                           'reg_tmp_2': reg_tmp_2.path } }}"

    - debug: var=add_to_body

但是,我无法通过查看set_fact对象或尝试访问result来找到hostvars操作后访问事实值的方法对于当前主机(显然是not possible inside a callback plugin)。

你有什么建议来解决这个限制?

1 个答案:

答案 0 :(得分:1)

嗯,你在这里混合了一些东西 如果您想在每项任务后调用v2_runner_on_ok中的API,则应在任务上下文中处理add_to_body 但是在您的示例中,您在完成多项任务后设置了add_to_body - 这样您就可以更好地编写动作插件(例如send_to_my_service)并使用所需参数调用它而不是set_fact

以下是如何在任务上下文中使用add_to_body的示例:

---
- hosts: localhost
  gather_facts: no

  tasks:
    - command: echo hello world
      vars:
        add_to_body:
          - path
    - file:
        dest: /tmp/zzz
        state: touch
      vars:
        add_to_body:
          - dest

回调:

def v2_runner_on_ok(self, result):
    if 'add_to_body' in result._task.vars:
        res = dict()
        for i in result._task.vars['add_to_body']:
            if i in result._result:
                res[i] = result._result[i]
            else:
                display.warning('add_to_body: asked to add "{}", but property not found'.format(i))
        display.v(res)