Ansible: how to construct a variable from another variable and then fetch it's value

匿名 (未验证) 提交于 2019-12-03 01:54:01

问题:

Here is my problem I need to use one variable 'target_host' and then append '_host' to it's value to get another variable name whose value I need. If you look at my playbook. Task nbr 1,2,3 fetch the value of variable however nbr 4 is not able to do what I expect. Is there any other way to achieve the same in ansible?

   ---     - name: "Play to for dynamic groups"       hosts: local        vars:         - target_host: smtp         - smtp_host: smtp.max.com       tasks:         - name: testing           debug: msg={{ target_host }}         - name: testing           debug: msg={{ smtp_host }}         - name: testing           debug: msg={{ target_host }}_host         - name: testing           debug: msg={{ {{ target_host }}_host }}   Output:  TASK: [testing] ***************************************************************  ok: [127.0.0.1] => {     "msg": "smtp" }  TASK: [testing] ***************************************************************  ok: [127.0.0.1] => {     "msg": "smtp.max.com" }  TASK: [testing] ***************************************************************  ok: [127.0.0.1] => {     "msg": "smtp_host" }  TASK: [testing] ***************************************************************  ok: [127.0.0.1] => {     "msg": "{{{{target_host}}_host}}" }

回答1:

You need to put quotes around it:

- hosts: local   vars: [ target_host: smtp ]   tasks:     debug: msg="{{ target_host }}_host"

-- edit --

My bad. Didn't read carefully enough.

This (AFAIK) isn't possible. The primary limitation that stops us doing this (no matter how you spin it), is 'variable expansion' in ansible is a single pass process and what you want requires multiple-passes.

Only [seriously hacky] ways I can think of are:

  • Create the playbook dynamically from your playbook using template and execute it.
  • I heard that Jinja2 engine does multi-pass evaluation. May be if you put these strings in a template and then use the lookup('template', ...) filter. Unfortunately I have no experience with Jinja2 templates so not quite sure if this is even an option.


回答2:

You can use "hostvars" to pass the variable, host facts can be loaded from group vars or host vars

yml

--- - name: "Play to for dynamic groups"   hosts: x0   vars:     - target_host: smtp   tasks:     - set_fact: smtp_host="smtp.max.com"     - set_fact: host_var_name={{target_host}}_host     - set_fact: dym_target_host={{hostvars[inventory_hostname][host_var_name]}}      - name: testing       debug: msg={{ target_host }}     - name: testing       debug: msg={{ smtp_host }}     - name: testing       debug: msg={{ target_host }}_host     - name: testing       debug: msg={{ dym_target_host }}

output:

PLAY [Play to for dynamic groups] *********************************************  GATHERING FACTS *************************************************************** ok: [x0]  TASK: [set_fact smtp_host="smtp.max.com"] ************************************* ok: [x0]  TASK: [set_fact host_var_name=smtp_host] ************************************** ok: [x0]  TASK: [set_fact dym_target_host={{hostvars[inventory_hostname][host_var_name]}}] *** ok: [x0]  TASK: [testing] *************************************************************** ok: [x0] => {     "msg": "smtp" }  TASK: [testing] *************************************************************** ok: [x0] => {     "msg": "smtp.max.com" }  TASK: [testing] *************************************************************** ok: [x0] => {     "msg": "smtp_host" }  TASK: [testing] *************************************************************** ok: [x0] => {     "msg": "smtp.max.com" }  PLAY RECAP ******************************************************************** x0                         : ok=8    changed=0    unreachable=0    failed=0


回答3:

I'm currently using the array-like syntax of Jinja 2. I don't think this is a great solution, but I've yet to find something better.

Let me give an example with one of my abstracted tasks. See my variable configuration and example task below:

# Variables file, available in the task context containers:   app:     image: mynamespace/myappcontainer:snapshot   web:     image: nginx:latest   db:     image: mariadb:latest    # Example task - name: Start containers   docker_container:     name: "{{ item }}"     image: "{{ containers[item].image }}"   with_items:     - app     - web     - db

In the above example I'm using the with_items Ansible loop, which runs the task for each item and makes the {{ item }} variable available accordingly.
This results in creating 3 Docker containers each with the proper container name based on the items list, and the proper image retrieved from the external variables I've configured.

Even though this example uses with_items, it is of course adaptable to your problem with use of your own variables.

Although this works perfectly fine in this situation, I'm afraid this requires the variables you'd like to access to be part of some parent variable (containers in this example). Therefore I'd recommend to split variables with a . to construct a hierarchy, and not with a _.

A variable like a.b.c where b is dynamic, would be accessible using a[b].c.
A variable like a.b where b is dynamic, would be accessible using a[b].


A solution you would use might look like (untested):

- name: "Play to for dynamic groups"   hosts: local    vars:     - target: smtp     - hosts:         smtp: smtp.max.com         imap: imap.max.com   tasks:     - name: testing       debug: msg={{ hosts[target] }}

Note that the variables are configured slightly differently, because it's structure is hierarchical.



回答4:

If you have a variable like

vars: myvar: xxx xxx_var: anothervalue

the working Ansible syntax:

- debug: msg={{ vars[myvar + '_var'] }}

will give you the analogue of:

- debug: msg={{ xxx_var }}



回答5:

You can nest your lookups like so:

--- - hosts: local   connection: local   gather_facts: no   vars:     target_host: smtp     lookup_host: "{{ target_host }}_host"     smtp_host: smtp.max.com   tasks:     - debug: var="{{ lookup_host }}"


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!