【问题标题】:ansible - variable within variableansible - 变量中的变量
【发布时间】:2015-12-18 16:27:48
【问题描述】:

Ansible 1.9.2 版本。

Ansible 在评估变量时是否支持变量内的变量扩展。

我的任务是从 Artifactory 下载 3 个 zip 文件。

我没有在角色中编写 3 个单独的任务,而是在剧本中使用了 ansible 的循环。在 Ansible 角色的 default/main.yml 中,我已经为角色定义/可用的所有必需变量,即 jmeterplugins_extras_artifactory_url 和其他(标准/webdriver)对 perf_tests 角色可见。

---
#- Download and install JMeterPlugins
# Use get_url when Ansible is 2.0+ is available on the machine (otherwise, we can't use get_url) thus, using wget.
- name: Download JMeterPlugins-*
  command: wget {{ jmeterplugins_{{ item.plugin }}_artifactory_url }}  
    chdir="{{ common_download_dir }}"
    creates="{{ common_download_dir }}/{{ jmeterplugins_{{ item.plugin }}_file }}"
  with_items:
    - { plugin: 'extras' }
    - { plugin: 'standard' }  
    - { plugin: 'webdriver' }   

但是使用上面的代码,我得到一个错误(如下所示):

15:58:57 TASK: [perf_tests | Download JMeterPlugins-*] ********************************* 
15:58:57 <jmeter01.super.fast.jenkins> ESTABLISH CONNECTION FOR USER: cmuser on PORT 22 TO jmeter01.super.fast.jenkins
15:58:57 fatal: [jmeter01.super.fast.jenkins] => Failed to template wget {{ jmeterplugins_{{ item.plugin }}_artifactory_url }} chdir="{{ common_download_dir }}" creates="{{ common_download_dir }}/{{ jmeterplugins_{{ item.plugin }}_file }}": template error while templating string: expected token 'variable_end', got '{'
15:58:57 
15:58:57 FATAL: all hosts have already failed -- aborting
15:58:57 
15:58:57 PLAY RECAP ******************************************************************** 
15:58:57            to retry, use: --limit @/home/cmuser/perf_tests.retry
15:58:57 
15:58:57 jmeter01.super.fast.jenkins : ok=23   changed=6    unreachable=1    failed=0   

如果一个变量包含另一个变量(尤其是当我使用循环时),ansible 不支持变量扩展/评估。

我只是不想将我的简单循环任务扩展为 3 个不同的名称任务,以分别下载 jmeterplugins_extras、jmeterplugins_standard 和 jmeterplugins_webdriver 的 zip 文件。该错误似乎与 Jinja 有关。

如何在另一个变量中使用var的值giga,即如果var包含giga,那么我应该得到变量“special_giga_variable”的值" ({{special_{{ var }}_variable}})?其中 var 在 defaults/main.yml 中定义为:

变量:千兆

【问题讨论】:

    标签: variables ansible ansible-playbook jinja2


    【解决方案1】:

    不,它没有。但这并不意味着您必须将其扩展为 3 个不同的任务。您可以做的实际上是将您的“字典”扩展为类似于以下内容:

    with_items:
     - {"url": "https://xxxxx", "file": "/tmp/xxxxx" }
     - {"url": "https://yyyyy", "file": "/tmp/yyyyy" }
     - {"url": "https://zzzzz", "file": "/tmp/zzzzz" }
    

    然后在你的任务中调用不同的参数:{{ item.url }} and {{ item.file }}

    备选方案:

    1. 编写您自己的过滤器,它将根据值{{ jmeterplugins_url | my_custom_filter(item.plugin) }}扩展您的变量

    2. 编写一个自定义模块,它将根据您的输入将获取 url 的所有功能封装到文件中

    3. 编写自定义lookup_plugin,它将遍历您的变量列表并产生正确的结果。

    4. 1234563

    【讨论】:

    • 我喜欢这样,我上周确实研究了那些认为我应该尝试最简单的方法。唯一的问题是,现在我必须在任务本身中定义实际的 URL 和文件值(并使其更混乱),而不是更简洁的方法。但是谢谢 Vor,我会试试这个 item.xxx 方法。我想知道,是否还有其他方法可以实现我真正想要的。
    • @ArunSangal 我添加了一些替代解决方案。他们将提供更多“更干净”的剧本,但只需要很少的工作来隐藏所有凌乱的连接。
    • 当然。我在看那些。这有何不同:{{ hostvars[inventory_hostname][fact_name] }}。我想知道这是否可行:{{ jmeterplugins_[item.plugin]_artifactory_url }} ... 即如果我可以使用大括号 [ ]
    【解决方案2】:

    确实如此。

    你可以使用

    set_fact:
      variable: '{{ vars['my_' + variablename + '_variable'] }}'
    

    到目前为止,这种方法的唯一缺点是,它不会动态扩展获取另一个变量值的变量。一个例子:

    roles/xxx/defaults/main.yml:

    var1: foo
    var2: '{{ var1 }}'
    

    不幸的是,这在尝试使用 var2 中的已解析值时不起作用。因此,

    - debug: msg='{{ vars["var2"] }}'
    

    将输出{{ var1 }} 而不是foo

    解决方法:

    在您的 vars 声明中,不要使用 var2: {{ var1 }},而是使用 var2: '{{ vars["var1"] }}'。这样,它就会起作用。

    【讨论】:

    • 超级好用!看起来有一个名为 vars 的全局变量。你每天都能学到新东西。
    • 很高兴看到 Ansible 官方页面记录了这一点。我还没有找到,如果有人找到这方面的官方文档,我将不胜感激。
    猜你喜欢
    • 2017-08-30
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2021-12-01
    • 2015-08-10
    • 1970-01-01
    • 2021-07-28
    • 2015-05-18
    相关资源
    最近更新 更多