Ansible:如何从另一个变量构造变量然后获取它的值

Max*_*Max 35 ansible

这是我的问题我需要使用一个变量'target_host',然后将'_host'附加到它的值,以获得另一个我需要的变量名称.如果你看看我的剧本.任务nbr 1,2,3获取变量的值,但nbr 4无法完成我的预期.在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}}"
}
Run Code Online (Sandbox Code Playgroud)

小智 34

如果你有一个像变量

vars: myvar: xxx xxx_var: anothervalue

工作的Ansible语法:

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

会给你类似的:

- debug: msg={{ xxx_var }}

  • 这对我来说就像一个魅力,完全符合它的需要.而且看起来更干净.应该是接受的答案. (3认同)
  • 它从Ansible 2.7开始工作,但是请注意,这不会扩展嵌套变量值。另外,`vars`被认为是“仅供内部使用”,因此可能会在没有警告的情况下中断。 (2认同)

eda*_*mon 15

从 Ansible 2.5 开始,使用varslookup plugin是可能的,我认为与此处发布的其他一些方法相比,它不太可能在没有警告的情况下中断。例如:

---
 - name: "Example of dynamic groups"
   hosts: localhost
   vars:
     - target_host: smtp
     - smtp_host: smtp.max.com
   tasks:
     - name: testing
       debug: msg={{ lookup('vars', target_host + '_host') }}
Run Code Online (Sandbox Code Playgroud)

输出:

PLAY [Example of dynamic groups] **************************************************

TASK [Gathering Facts] **************************************************
ok: [localhost]

TASK [testing] **************************************************
ok: [localhost] => {
    "msg": "smtp.max.com"
}

Run Code Online (Sandbox Code Playgroud)


lic*_*hon 13

您可以使用"hostvars"传递变量,可以从组变量或主变量中加载主机事实

阳明海运

---
- 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 }}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)


Kas*_*yap 8

你需要在它周围加上引号:

- hosts: local
  vars: [ target_host: smtp ]
  tasks:
    debug: msg="{{ target_host }}_host"
Run Code Online (Sandbox Code Playgroud)

- 编辑 -

Kashyap 我需要比这多上一层。想象一下,还有另一个变量“smtp_host”,我想在运行时使用另一个变量(target_host)构造该变量并将字符串“_host”附加到它。= {{ {{ target_host }}_host }} – 最大

我的错。读的不够仔细。

这(AFAIK)是不可能的。阻止我们这样做的主要限制(无论您如何旋转),是 ansible 中的“变量扩展”是单遍过程,而您想要的则需要多遍。

我能想到的唯一 [严重 hacky] 方法是:

  • 使用您的剧本动态创建剧本template并执行它。
  • 听说那个Jinja2的引擎做多遍评价。可能是如果您将这些字符串放在模板中然后使用lookup('template', ...)过滤器。不幸的是,我没有使用 Jinja2 模板的经验,所以不太确定这是否是一种选择。

  • 每次有人在剧本中调用“ansible-playbook test.yml -i hosts”时,小猫就会死亡。 (12认同)
  • 仅供参考,这个答案已经过时了——从 Ansible 2.5 开始,可以使用 [`vars` 查找插件](https://docs.ansible.com/ansible/latest/plugins/lookup/vars.html)。 (2认同)

Tim*_*sée 6

我目前正在使用Jinja 2的类似数组的语法。我认为这不是一个很好的解决方案,但我还没有找到更好的解决方案。

让我举一个我的抽象任务的例子。请参阅下面的变量配置和示例任务:

# 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
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我使用with_itemsAnsible循环,它为每个项目运行任务并{{ item }}相应地使变量可用。
这会导致创建 3 个 Docker 容器,每个容器都具有基于项目列表的正确容器名称,以及从我配置的外部变量中检索到的正确图像。

尽管此示例使用with_items,它当然可以通过使用您自己的变量来适应您的问题。

尽管这在这种情况下工作得很好,但恐怕这需要您想要访问的变量成为某些父变量的一部分(containers在本例中)。因此,我建议使用 a 来拆分变量.来构建层次结构,而不是使用_.

a.b.c像where是动态的变量b可以使用a[b].c. 像where是动态的
变量可以使用.a.bba[b]


您将使用的解决方案可能如下所示(未经测试):

- 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] }}
Run Code Online (Sandbox Code Playgroud)

请注意,变量的配置略有不同,因为它的结构是分层的。


小智 5

您有两种方式可以选择:
1. 一般使用。

vars:
    - target_host: smtp
    - smtp: smtp.max.com
tasks: 
    - name: testing
        debug: msg={{ target_host }}
    - name: testing
        debug: msg={{ smtp }}
    - name: testing
        debug: msg={{ vars[target_host] }}
Run Code Online (Sandbox Code Playgroud)

2. 使用事实

tasks: 
    - set_fact: target_host=smtp
    - set_fact: smtp=smtp.max.com
    - name: testing
        debug: msg={{ target_host }}
    - name: testing
        debug: msg={{ smtp }}
    - name: testing
        debug: msg={{hostvars[inventory_hostname][target_host]}}
Run Code Online (Sandbox Code Playgroud)