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

时间:2015-03-26 10:29:29

标签: 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}}"
}

10 个答案:

答案 0 :(得分:22)

如果您有像

这样的变量

vars: myvar: xxx xxx_var: anothervalue

工作的Ansible语法:

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

会给你类似的:

- debug: msg={{ xxx_var }}

答案 1 :(得分:13)

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

  

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

输出:

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

答案 2 :(得分:5)

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

---
 - 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') }}

输出:

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

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

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

答案 3 :(得分:4)

您有两种选择方式:
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] }}

2。使用fact

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

答案 4 :(得分:3)

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

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

- 编辑 -

  

Kashyap我需要比这更高一级。想象一下   另一个变量' smtp_host'我想构建那个变量   运行时使用另一个变量(target_host)并附加一个字符串   ' _host'它。 = {{{{target_host}} _ host}} - 最大

我的坏。没有仔细阅读。

这(AFAIK)是不可能的。阻止我们这样做的主要限制(无论你怎么旋转它),是变量扩展'在ansible中是一个单程过程,你想要的是多次传递。

我认为只有[严重的hacky]方式:

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

答案 5 :(得分:3)

我目前正在使用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

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

即使此示例使用with_items,它当然也适用于使用您自己的变量的问题。

虽然这种情况在这种情况下完全正常,但我担心这需要您要访问的变量成为某个父变量(本例中为containers)的一部分。因此,我建议使用.拆分变量以构建层次结构,而不是使用_

a.b.c这样的变量,其中b是动态的,可以使用a[b].c访问。
a.b这样的变量(b是动态的)可以使用a[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] }}

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

答案 6 :(得分:0)

您可以像这样嵌套查找:

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

答案 7 :(得分:0)

在我看来,您可以仅使用var选项代替msg

  debug: var="{{ target_host }}_host"

礼物:

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

答案 8 :(得分:0)

上面有很多答案。这对我帮助很大。但是我还没有找到如何将这些变量保存在vars-> main.yml文件中的单一答案。 因此,您必须在vars-> main.yml文件中创建一个字典。

vars-> main.yml文件

cassandra_version: 2.1.16
file_sha_cassandra: "apache-cassandra-{{ cassandra_version }}_sha256"
# Create Dictionary here
cassandra:
    apache-cassandra-2.1.16_sha256: "sha256: checksum_of_file"
    ##Add more variable

现在您必须在任务-> main.yml文件中调用它:

---
  - name: Down load Cassandra Binaries
    get_url:
       url: "file_url"
       dest: "{{ base_directory }}"
       checksum: "{{ cassandra[file_sha_cassandra] }}"
       timeout: 800

答案 9 :(得分:0)

您可以尝试使用全局数组var:

regions:
  us-east-1:
    endpoint: rds.us-east-1.amazonaws.com
  cn-north-1:
    endpoint: rds.cn-north-1.amazonaws.com.cn
  cn-northwest-1:
    endpoint: rds.cn-northwest-1.amazonaws.com.cn

并使用它来获取依赖于另一个的价值

region_endpoint: "{{ regions[region].endpoint}}"

在您的情况下:

target_host:
  imap:
    host: imap.max.com
  smtp:
    host: smtp.max.com

然后:

region_endpoint: "{{ target_host[service].host}}"