Ansible:如何从另一个变量构造一个变量,然后获取它';s值

Ansible:如何从另一个变量构造一个变量,然后获取它';s值,ansible,Ansible,这里是我的问题,我需要使用一个变量'target_host',然后将'u host'附加到它的值,以获得另一个我需要其值的变量名。 如果你看我的剧本。任务nbr 1,2,3获取变量的值,但是nbr 4无法执行我期望的操作。在ansible中有没有其他方法可以达到同样的效果 --- - name: "Play to for dynamic groups" hosts: local vars: - target_host: smtp

这里是我的问题,我需要使用一个变量'target_host',然后将'u 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}}"
}

您需要在其周围加上引号:

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


卡希亚普,我需要再上一层楼。想象一下有 另一个变量'smtp_host',我想在 运行时使用另一个变量(target_host)并附加字符串 它的“主机”{{{{target{u host}}}{u host}}–Max

我的错。读得不够仔细

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

我能想到的唯一(严重的)方法是:

  • 使用
    模板
    从playbook动态创建playbook并执行它
  • 我听说Jinja2发动机进行了多次评估。如果您将这些字符串放入模板中,然后使用
    查找('template',…)
    过滤器,则可能会出现这种情况。不幸的是,我没有使用Jinja2模板的经验,所以不太确定这是否是一个选项

您可以这样嵌套查找:

---
- 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 }}"
您可以使用“hostvars”传递变量,可以从组变量或主机变量加载主机事实

yml

输出:


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

让我以我的一个抽象任务为例。请参见下面的我的变量配置和示例任务:

#变量文件,在任务上下文中可用
容器:
应用程序:
图像:mynamespace/myappcontainer:快照
网状物:
图片:nginx:latest
db:
图片:mariadb:最新
#示例任务
-名称:启动容器
docker_集装箱:
名称:“{{item}}”
图像:“{containers[item].image}”
有以下项目:
-应用程序
-网
-分贝
在上面的示例中,我使用的是Ansible循环,它为每个项目运行任务,并相应地使
{{item}}
变量可用。
这将导致创建3个Docker容器,每个容器都具有基于items列表的正确容器名称,以及从我配置的外部变量检索到的正确图像

即使这个例子使用了
和_items
,它当然也适用于您使用自己变量的问题

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

A.b.c
这样的变量,其中
b
是动态的,可以使用
A[b].c

A.b
这样的变量,其中
b
是动态的,可以使用
A[b]
访问


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

-name:“为动态组播放”
主持人:本地
变量:
-目标:smtp
-主持人:
smtp:smtp.max.com
imap:imap.max.com
任务:
-名称:测试
调试:msg={{hosts[target]}

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

如果您有一个类似

vars:
myvar:xxx
xxx\u变量:另一个值

可用的Ansible语法:

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

将为您提供以下模拟:


-debug:msg={{xxx\u var}
您有两种选择方式:
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] }}
二,。使用


在我看来,您可以使用
var
选项而不是
msg

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

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

上面有很多答案。这对我帮助很大。但我还没有找到一个答案,如何将这些变量保存在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
现在您必须在task->main.yml文件中调用此函数:

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

您可以尝试全局数组变量:

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
然后:


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


卡希亚普,我需要再上一层楼。假设有另一个变量“smtp_host”,我想在运行时使用另一个变量(target_host)构造该变量,并将字符串“_host”附加到该变量上{{{{{target{u host}}{u host}}每次有人在剧本中调用“ansible playbook test.yml-i hosts”,小猫就会死。模板看起来是最合理的解决方案。我不喜欢猫,下面是从Ansible调用Ansible的过程。仅供参考,这个答案已经过时了——这在Ansible 2.5中是可能的。这只适用于
debug:var=
的特殊情况,因为它是特殊的。不能将其传递给其他模块。例如,
debug:msg=“{{lookup\u host}}”
shell:echo“{{lookup\u host}}”
这看起来是实现我想要的目标的一个好方法。@kashyap解释中需要注意的重要一点是“ansible中的‘变量扩展’是一个单过程”我不认为它是单过程,因为
[]
中的变量被计算,并且它的值被用作键。如果需要,可以将多个支架链接在一起。不管怎么说,很高兴听到这可能对你有用!我会看看我是否可以通过查看源代码来掩盖它,或者从开发者社区寻求帮助
target_host:
  imap:
    host: imap.max.com
  smtp:
    host: smtp.max.com
region_endpoint: "{{ target_host[service].host}}"
---
 - 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"
}