在Solaris上,Ansible的setup
模块不会收集有关已安装区域的信息。如何扩展setup
模块以收集zoneadm list -iv
的输出?
答案 0 :(得分:3)
创建一个名为/etc/ansible/facts.d/zoneadm.fact
的脚本,并收集您需要的任何信息。这可以是你想要的任何东西(bash / python / etc)。
完成后,echo
以stson格式标出它。
通过ansible部署该脚本,使其可执行
收集事实并注意ansible_local.zoneadm
可以找到更多信息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)。