只要记住这个,Ansible(动态)变量就不再可怕了

概述

在使用Ansible的过程中,您可能会遇到在playbook中无法动态设置变量(使用set_fact)以创建所需值的情况。刚开始使用Ansible时,我也曾纠结于如何创建这样的变量……最后,我只能写出冗长且不完美的代码。然而,通过使用块样式和Jinja模板,您可以自由自在地创建变量,所以再也不用为此烦恼了!

方块风格

一种类似于Here Document的方式,可以将多行值输入给变量或处理。这样做还可以提高可读性(例如↓)。

> cat << EOF
The Ansible Advent Calendar !!!
Enjoy Ansible ♪
EOF

------------------
出力結果
------------------
The Ansible Advent Calendar !!!
Enjoy Ansible ♪

在 Ansible 中,可以这样表达:
确切来说,它被称为块标量样式,被定义在 YAML 参考文档中。

- set_fact:
    example: >
      The Ansible Advent Calendar !!!
      Enjoy Ansible ♪

------------------
出力結果
------------------
ok: [localhost] => {
    "example": "The Ansible Advent Calendar !!! Enjoy Ansible ?\n"
}

在上面的例子中,我們使用了(folded style),但是從結果可以看出,中間的換行符(\n)被去除了。
如果需要換行,我們可以使用|(literal style)。另外,在最後一行也可以指定是否換行,請參考這個易於理解的解釋網站,確認它們之間的區別!

Jinja模板

通过在前述的块样式中充分利用它,您可以自如地操纵变量。这是大家所熟悉的Jinja模板在Ansible中的应用!

基础编程


# monthが12の場合は、"The Ansible xxxx...(省略)"と表示
# そうではない場合は、"Coming soon..."と表示
- set_fact:
    example: >-
      {%- set month = 12 -%}
      {%- if month == 12 -%}
        The Ansible Advent Calendar !!!
        Enjoy Ansible ♪
      {%- else -%}
        Coming soon...
      {%- endif -%}

------------------
出力結果
------------------
ok: [localhost] => {
    "example": "The Ansible Advent Calendar !!! Enjoy Ansible ?\n"
}

优点

由于Jinja模板中可以使用各种语句,因此可以在{%-%}之间实现条件分支、循环和变量生成。

应用程序设计


# キーaの値が3のdictにnew_dictを追加する
- set_fact:
    my_list_dict: [{'a': 1, 'b': 2},{'a': 3, 'd': 2}]
    new_dict: {'c': 4}

- set_fact:
    example2: >-
      {%- set _my_list_dict = my_list_dict -%}
      {%- for _dict in _my_list_dict -%}
        {%- if _dict['a'] == 3 -%}
          {%- set dummy = _dict.update(new_dict) -%}
        {%- endif -%}
      {%- endfor -%}
      {%- set dummy = _my_list_dict.append({'a': 5, 'z': 0}) -%}
      {{ _my_list_dict }}

------------------
出力結果
------------------
ok: [localhost] => {
    "example2": [
        {
            "a": 1,
            "b": 2
        },
        {
            "a": 3,
            "c": 4,
            "d": 2
        },
        {
            "a": 5,
            "z": 0
        }
    ]
}

第一点

已经在set_fact中定义的变量可以在模板中使用,但在模板中定义的变量的作用域仅限于模板内部。如果要将变量赋值给set_fact中的变量(my_list_dict),需要以{{ _my_list_dict }}的格式输出。输出时也会保证变量的类型(如列表、字典等)。但是,如果多次输出,则会被视为字符串。

第二点

在更新现有变量时,类似于`{%- set dummy = _dict.update(new_dict) -%}`的代码会向_dict中添加new_dict。由于必须使用`set 变量名 = 值`的格式来更新变量,因此使用了名为dummy的变量。

来自@fumiyas的建议

从@fumiyas处得到的建议

[defaults]
jinja2_extensions=jinja2.ext.do

听说可以通过这样做来达到效果:不用设置dummy = _dict.update(new_dict),而是可以直接写成 do _dict.update(new_dict)。

第三点

在Python中,list类型可以使用append方法来添加元素,而dict类型则可以使用update方法来更新元素。

bannerAds