只要记住这个,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方法来更新元素。