简体   繁体   English

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

[英]Ansible: How to get a value of a variable from the inventory or group_vars file?

How do I get the value of a variable from the inventory if the variable could be either in the inventory file or group_vars directory?如果变量可以在清单文件或group_vars目录中,我如何从清单中获取变量的值?

For example, region=place-a could be in the inventory file or in a file in the group_vars somewhere.例如, region=place-a可以在清单文件中或在group_vars某处的文件中。 I would like a command to be able to retrieve that value using ansible or something retrieve that value.我想要一个命令能够使用 ansible 或检索该值的东西检索该值。 like:像:

$ ansible -i /somewhere/production/web --get-value region
place-a

That would help me with deployments and knowing which region is being deployed to.这将帮助我进行部署并了解正在部署到哪个区域。

. .

A longer explanation to clarify, my inventory structure looks like this:更长的解释要澄清,我的库存结构如下所示:

/somewhere/production/web
/somewhere/production/group_vars/web

The contents with the variables of the inventory file, /somewhere/production/web looks like this:库存文件的变量内容/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

I could get the value from the inventory file by simply parsing the file.我可以通过简单地解析文件从清单文件中获取值。 like so:像这样:

$ awk -F "=" '/^region/ {print $2}' /somewhere/production/web
place-a

But that variable could be in the group_vars file, too.但该变量也可以在group_vars文件中。 For example:例如:

$ cat /somewhere/production/group_vars/web
region: place-a

Or it could look like an array:或者它看起来像一个数组:

$ cat /somewhere/production/group_vars/web
region:
    - place-a

I don't want to look for and parse all the possible files.我不想查找和解析所有可能的文件。

Does Ansible have a way to get the values? Ansible 是否有获取值的方法? Kind of like how it does with --list-hosts ?有点像它如何处理--list-hosts

$ ansible web -i /somewhere/production/web --list-hosts
    web1
    web2

Short Answer简答

NO there is no CLI option to get value of variables.,没有 CLI 选项来获取变量的值。

Long Answer长答案

First of all, you must look into how variable precedence works in Ansible.首先,您必须研究变量优先级在 Ansible 中的工作原理。

The exact order is defined in the documentation .确切的顺序在文档中定义。 Here is an summary excerpt:以下是摘要摘录:

Basically, anything that goes into “role defaults” (the defaults folder inside the role) is the most malleable and easily overridden.基本上,进入“角色默认值”(角色内的默认值文件夹)的任何内容都是最具延展性和最容易覆盖的。 Anything in the vars directory of the role overrides previous versions of that variable in namespace.角色的 vars 目录中的任何内容都会覆盖名称空间中该变量的先前版本。 The idea here to follow is that the more explicit you get in scope, the more precedence it takes with command line -e extra vars always winning.这里要遵循的想法是,您在范围内获得的越明确,命令行 -e extra vars 总是获胜的优先级越高。 Host and/or inventory variables can win over role defaults, but not explicit includes like the vars directory or an include_vars task.主机和/或清单变量可以胜过角色默认值,但不能像 vars 目录或 include_vars 任务那样显式包含。

With that cleared out, the only way to see what value is a variable taking is to use the debug task as follows:清除后,查看变量取什么值的唯一方法是使用debug任务,如下所示:

- name: debug a variable
  debug:
    var: region

This will print out the value of the variable region .这将打印出变量region的值。

My suggestion would be to maintain a single value type, either a string or a list to prevent confusion across tasks in different playbooks .我的建议是保持一个单一的值类型,一个string或一个list以防止不同playbooks tasks混淆。

You could use something like this:你可以使用这样的东西:

- name: deploy to regions
  <task_type>:
    <task_options>: <task_option_value>
    // use the region variable as you wish
    region: {{ item }}
    ...
  with_items: "{{ regions.split(',') }}"

In this case you could have a variable regions=us-west,us-east comma-separated.在这种情况下,您可以有一个变量regions=us-west,us-east逗号分隔。 The with_items statement would split it over the , and repeat the task for all the regions. with_items语句会将其拆分为,并为所有区域重复该任务。

The CLI version of this is important for people who are trying to connect ansible to other systems.这个 CLI 版本对于试图将 ansible 连接到其他系统的人来说很重要。 Building on the usage of the copy module elsewhere, if you have a POSIX mktemp and a copy of jq locally, then here's a bash one-liner that does the trick from the CLI:建立在其他地方使用copy模块的基础上,如果您在本地有一个 POSIX mktempjq的副本,那么这里有一个 bash one-liner,它可以通过 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}

Breaking it down打破它

# 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}

Another more easy solution get a variable through cli from ansible could be this:通过 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

Looks quite ugly but is really helpful.看起来很丑,但真的很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM