Ansible:在循环中生成变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ansible:在循环中生成变量相关的知识,希望对你有一定的参考价值。

在我的变量文件中,我需要定义一个列表变量,其项目具有相似的模式,并且还共享一些(冗余)信息。我想在循环中生成列表变量,而不是手动输入所有这些信息。

例如,我有100个主机,主IP地址为192.168.100。[1:100],每个主机有一个额外的IP地址10.0.1。[1:100]。所有主IP使用相同的网关,例如192.168.100.254,所有额外的IP使用另一个网关,例如10.0.1.254。

在一项任务中,我想循环遍历所有主机,并且对于每个主机,它都是主要的ip,额外的ip和网关都是需要的。我想在我的任务中使用“with_items”,所以我希望有一个列表变量“IP_ADDRS”,其中每个项目都是如下所示:

{ primary_ip: 192.168.100.x, primary_gw: 192.168.100.254, extra_ip: 10.0.1.x, extra_gw: 10.0.1.254}

而不是手动定义IP_ADDRS:

IP_ADDRS:
  - { primary_ip: 192.168.100.1, primary_gw: 192.168.100.254, extra_ip: 10.0.1.1, extra_gw: 10.0.1.254}
  - { primary_ip: 192.168.100.2, primary_gw: 192.168.100.254, extra_ip: 10.0.1.2, extra_gw: 10.0.1.254}
  - ...

我想以某种方式生成列表变量“IP_ADDRS”...

我尝试了jinja2语句,如下所示:

IP_ADDRS: >
  "{% for idx in range(1, 101) %}
  - { primary_ip: 192.168.100.{{ idx }}, primary_gw: 192.168.100.254, extra_ip: 10.0.1.{{ idx }}, extra_gw: 10.0.1.254 }
  "{% endfor %}"

当我使用调试模块打印IP_ADDRS时,它确实打印列表中的所有项目,但似乎Ansible不将此变量视为LIST,因此

with_items:{{IP_ADDRS}}

不像我预期的那样工作。

jinja2语句有什么问题,还是有办法实现相同的结果?

非常感谢,

/棕色

答案

您可以定义对象的模板并在循环中使用它:

---
- hosts: localhost
  gather_facts: no
  vars:
    ip_template:
      primary_ip: "192.168.100.{{ item }}"
      primary_gw: "192.168.100.254"
      extra_ip: "10.0.1.{{ item }}"
      extra_gw: "10.0.1.254"
  tasks:
    # execute single task, no need in list
    - debug:
        msg: "{{ ip_template }}"
      with_sequence: "start=1 count=5"

    # construct list
    - set_fact:
        ip_list: "{{ (ip_list | default([])) + [ip_template] }}"
      with_sequence: "start=1 count=5"
    - debug:
        msg: "{{ ip_list }}"

如果您仍希望在变量中定义ip_list,则需要构建复杂的Jinja2语句以生成JSON格式的列表而不是YAML,就像您尝试的那样。这种字符串的小例子里面有两个对象:'[{"ip":"192.168.0.10","gw":"192.168.0.1"},{"ip":"192.168.0.20","gw":"192.168.0.1"}]'

另一答案

如果需要由loopsif/else生成许多复杂变量。有时候,当尝试在任务中生成它们时,它会变得讨厌且不易理解。以jinja模板格式创建变量文件可能会有所帮助。

例如,创建jinja模板生成的变量:

# variable file
{% for idx in range(1, 101) %}
- primary_ip: 192.168.100.{{ idx }}
  primary_gw: 192.168.100.254
  extra_ip: 10.0.1.{{ idx }}
  extra_gw: 10.0.1.254
{% endfor %}

然后通过template查找插件读取任务中的变量:

# playbook tasks
- name: Read variables
  set_fact:
    ip_list: "{{ lookup('template', 'path_to_file') | from_yaml }}"

结果将是:

TASK [set_fact] *******************************************************************************************************************
Tuesday 06 February 2018  17:16:55 +0800 (0:00:00.110)       0:00:00.110 ******
Tuesday 06 February 2018  17:16:55 +0800 (0:00:00.108)       0:00:00.108 ******
ok: [localhost]

TASK [debug] **********************************************************************************************************************
Tuesday 06 February 2018  17:16:55 +0800 (0:00:00.137)       0:00:00.247 ******
Tuesday 06 February 2018  17:16:55 +0800 (0:00:00.137)       0:00:00.245 ******
ok: [localhost] => {
    "ip_list": [
        {
            "extra_gw": "10.0.1.254",
            "extra_ip": "10.0.1.1",
            "primary_gw": "192.168.100.254",
            "primary_ip": "192.168.100.1"
        },
        {
            "extra_gw": "10.0.1.254",
            "extra_ip": "10.0.1.2",
            "primary_gw": "192.168.100.254",
            "primary_ip": "192.168.100.2"
        },
        ...........

以上是关于Ansible:在循环中生成变量的主要内容,如果未能解决你的问题,请参考以下文章

Ansible 循环遍历字典和列表

Ansible嵌套循环,如何基于外部变量设置内部循环变量

Ansible循环x次

使用loop_var Ansible循环多个变量

Ansible自动化运维Ansible变量之lookup生成变量方法

Ansible 学习总结—— Ansible 循环条件判断触发器处理失败等任务控制使用总结