Ansible:如何从 inventory 或 group_vars 文件中获取变量的值?

问题描述 投票:0回答:4

如果变量可以位于清单文件或

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
ansible
4个回答
1
投票

简短回答

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
语句会将其拆分为
,
并为所有区域重复该任务。


1
投票

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}

0
投票

另一个更简单的解决方案,通过 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

看起来很丑,但确实很有帮助。


0
投票

到目前为止我发现的最好方法是使用带有 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 也非常有用。

© www.soinside.com 2019 - 2024. All rights reserved.