如果变量可以位于清单文件或
group_vars
目录中,如何从清单中获取变量的值?
例如,
region=place-a
可能位于库存文件中或位于 group_vars
某处的文件中。我希望命令能够使用 ansible 或其他方式检索该值来检索该值。喜欢:
$ ansible -i /somewhere/production/web --get-value region
place-a
这将帮助我进行部署并了解要部署到哪个区域。
.
需要更长的解释来澄清,我的库存结构如下所示:
/somewhere/production/web
/somewhere/production/group_vars/web
库存文件的变量内容,
/somewhere/production/web
看起来像这样:
[web:children]
web1 ansible_ssh_host=10.0.0.1
web2 ansible_ssh_host=10.0.0.2
[web:vars]
region=place-a
我可以通过简单地解析文件来从库存文件中获取值。像这样:
$ awk -F "=" '/^region/ {print $2}' /somewhere/production/web
place-a
但是该变量也可能位于
group_vars
文件中。例如:
$ cat /somewhere/production/group_vars/web
region: place-a
或者它可能看起来像一个数组:
$ cat /somewhere/production/group_vars/web
region:
- place-a
我不想寻找并解析所有可能的文件。
Ansible 有办法获取这些值吗?有点像
--list-hosts
?
$ ansible web -i /somewhere/production/web --list-hosts
web1
web2
NO 没有 CLI 选项来获取变量的值。
首先,您必须研究变量优先级在 Ansible 中如何工作。
确切的顺序在文档中定义。以下是摘要摘录:
基本上,任何进入“角色默认值”的内容(默认值 角色内的文件夹)是最具延展性且易于覆盖的。 角色的 vars 目录中的任何内容都会覆盖以前的版本 命名空间中该变量的。这里要遵循的想法是 范围越明确,它的优先级就越高 命令行 -e extra vars 总是获胜。主机和/或库存 变量可以胜过角色默认值,但不能显式包含,例如 vars 目录或 include_vars 任务。
清除了这一点后,查看变量取什么值的唯一方法是使用
debug
任务,如下所示:
- name: debug a variable
debug:
var: region
这将打印出变量的值
region
。
我的建议是保持单一值类型,要么是
string
要么是 list
,以防止不同 tasks
中的 playbooks
发生混淆。
你可以使用这样的东西:
- name: deploy to regions
<task_type>:
<task_options>: <task_option_value>
// use the region variable as you wish
region: {{ item }}
...
with_items: "{{ regions.split(',') }}"
在这种情况下,您可以有一个以逗号分隔的变量
regions=us-west,us-east
。 with_items
语句会将其拆分为 ,
并为所有区域重复该任务。
CLI 版本对于尝试将 ansible 连接到其他系统的人来说非常重要。 在其他地方使用
copy
模块的基础上,如果您本地有 POSIX mktemp
和 jq 的副本,那么这里有一个 bash 单行代码可以从 CLI 中实现这一点:
export TMP=`mktemp` && ansible localhost -c local -i inventory.yml -m copy -a "content={{hostvars['SOME_HOSTNAME']}} dest=${TMP}" >/dev/null && cat ${TMP}|jq -r .SOME_VAR_NAME && rm ${TMP}
分解它
# create a tempfile
export TMP=`mktemp`
# quietly use Ansible in local only mode, loading inventory.yml
# digging up the already-merged global/host/group vars
# for SOME_HOSTNAME, copying them to our tempfile from before
ansible localhost --connection local \
--inventory inventory.yml --module-name copy \
--args "content={{hostvars['SOME_HOSTNAME']}} dest=${TMP}" \
> /dev/null
# CLI-embedded ansible is a bit cumbersome. After all the data
# is exported to JSON, we can use `jq` to get a lot more flexibility
# out of queries/filters on this data. Here we just want a single
# value though, so we parse out SOME_VAR_NAME from all the host variables
# we saved before
cat ${TMP}|jq -r .SOME_VAR_NAME
rm ${TMP}
另一个更简单的解决方案,通过 cli 从 ansible 获取变量可能是这样的:
export tmp_file=/tmp/ansible.$RANDOM
ansible -i <inventory> localhost -m copy -a "content={{ $VARIABLE_NAME }} dest=$tmp_file"
export VARIBALE_VALUE=$(cat $tmp_file)
rm -f $tmp_file
看起来很丑,但确实很有帮助。
到目前为止我发现的最好方法是使用带有 JSON 输出插件的调试模块。显然,这需要调用ansible。优点是,这正是你的剧本在运行时看到的,即你合并了所有的 group_vars 并替换了“{{ jinja_expressions }}”(ansible-inventory 不会为你评估 Jinja)。
ANSIBLE_LOAD_CALLBACK_PLUGINS=true \
ANSIBLE_STDOUT_CALLBACK=json \
ansible \
--connection local \
--inventory=inventory \
-m debug \
-a var="hostvars" \
localhost \
| jq \
--arg host somehost \
--arg var somevar \
--raw-output \
'.localhost.hostvars[$host][$var]'
这对于将所有主机的完整主机变量导出到 JSON 也非常有用。