如何扩展Ansible的设置模块以收集更多信息?

时间:2016-10-26 12:00:27

标签: ansible solaris

在Solaris上,Ansible的setup模块不会收集有关已安装区域的信息。如何扩展setup模块以收集zoneadm list -iv的输出?

3 个答案:

答案 0 :(得分:3)

  1. 创建一个名为/etc/ansible/facts.d/zoneadm.fact的脚本,并收集您需要的任何信息。这可以是你想要的任何东西(bash / python / etc)。

  2. 完成后,echo以stson格式标出它。

  3. 通过ansible部署该脚本,使其可执行

  4. 收集事实并注意ansible_local.zoneadm

  5. 下的新事实

    可以找到更多信息here

答案 1 :(得分:2)

我在2年前处理同样的困境。以前的回复是正确的,但您必须先部署一些内容并重新运行Ansible以获取新的事实。

可以选择编写自己的Ansible模块,该模块返回JSON,如下所示:

{
  'changed': false,
  'ansible_facts': {
     'sunos': {
       'zonename': 'global',
       'zones': {},
  }
}

然后将此类模块返回的事实合并为来自setup模块的事实。为了更加可移植,最好将此类模块包含在Ansible角色中,并且只包含一个调用此模块的任务,并添加标记always,即使您通过在cmdline上指定标记来选择任务子集,也可以运行此事实集合。

我有我的旧角色pushed here on GitHub。可能不会开箱即用......与Ansible 1.0一起使用,但会受到启发。

答案 2 :(得分:0)

我误解的原因是,我想,我必须在Ansible机器上放置一些东西,它会在模块完成时自动部署到目标系统。但事实收集工作方式不同!在setup开始工作之前,必须采取措施,即fatcs收集脚本已经在目标系统上。我会说这是Ansible中的设计错误,或者至少是一个尚未实现的功能。

要添加此缺少的功能,必须编写一个播放,该播放在所有其他内容之前有效。我提出了以下解决方案:

---
- name: facts deployment
  gather_facts: false
  hosts: all
  become: true
  tasks:
    - set_fact: setup_necessary=false
    - file:
        path: "/etc/ansible/facts.d"
        state: directory
        recurse: yes
      register: facts_directory
    - set_fact: setup_necessary=true
      when: facts_directory.changed

- name: solaris facts
  gather_facts: false
  hosts: solaris
  become: true
  tasks:
    - include: deploy_fact.yml
      with_items:
        - { shell: bash, file: nonglobal_zones }
        - { shell: bash, file: solaris_eeprom }

- name: setup after facts update
  gather_facts: false
  hosts: all
  tasks:
    - setup:
      when: setup_necessary

上面的Playbook会使用gather_facts: false进行播放,以防止在部署事实之前运行任何setup。当对目标系统进行任何更改时,所有播放都会设置变量setup_necessary。不可能为此使用处理程序,因为处理程序在游戏结束时运行,但不在剧本结束时或在某些游戏之后(Ansible限制1)。

首先创建目录,然后部署所有事实文件。有必要将外观的主体放入单独的任务文件中,因为无法在剧本中将两个任务组合在一起(Ansible limit 2)。

deploy_fact.yml文件的内容使用template模块将事实脚本传输到目标系统。

---
- name: "/etc/ansible/facts.d/{{item.file}}.fact"
  template:
    src: "{{inventory_dir}}/facts.d/{{item.shell}}.j2"
    dest: "/etc/ansible/facts.d/{{item.file}}.fact"
    mode: 0755
  register: facts_file
- set_fact: setup_necessary=true
  when: facts_file.changed

我使用template模块的原因是,每个事实脚本都需要某种错误处理,这样可以在发生错误时创建正确的JSON。这是我目前的错误处理,但它仍然可以改进。有些人也不喜欢set -eu,这在某种程度上是一种品味。

#! /bin/bash
{% include item.file + '.bash' %}


set -eu

_stderr=$(mktemp)
trap 'rm -f "$_stderr"' EXIT
if _stdout=$(main 2>$_stderr); then
  if [ "$_stdout" ]; then
    echo "$_stdout"
  else
    echo null
  fi
else
  jq -Rsc "{\"ERROR\":{\"failed\":true,\"exit\":$?,\"msg\":.}}" $_stderr
fi

模板只是通过隐式item变量包含循环传递的文件。包装器期望从包含的文件中定义main个函数。这是我对非全局区域的主要功能:

main ()
{
  zoneadm list -i |
  grep -v global |
  jq -Rc . |
  jq -sc .
}

这个收集Solaris eeprom数据:

main ()
{
  eeprom |
  sed 's/^\([^=]*\)=\(.*\)$/{"\1":"\2"}/' |
  sed 's/^\(.*\): data not available.$/{"\1":null}/' |
  sed 's/:"false"}$/:false}/g' |
  sed 's/:"true"}$/:true}/g' |
  sed 's/:"\([0-9][0-9]*\)"}$/:\1}/' |
  sed '/^{"boot-device"/{s/":"/":["/;s/ /","/g;s/"}$/"]}/;}' |
  jq -sc add
}

我的底线是,在某种程度上可以扩展Ansible的事实收集,但它远非显而易见,而且有点痛苦,因为它使setup模块的临时使用变得不可能。 Ansible不应要求用户实现上述内容,而应将上述所有内容移至setup模块(Ansible restriction 3)。