如何编写一个从模板创建文件的 ansible 任务,以便仅在第一次由 ansible 配置该文件时更新模板源文件中的 Jinja2 变量? 考虑文件
my-service.conf
user = 'admin'
password = 'fxbff4w146lx813fjiead353fnpbfoqz'
some_other_option = 'yes'
我想要的是在ansible配置文件时自动生成密码,所以我创建了这个Jinja2模板文件
my-service.conf.j2
user = 'admin'
password = '{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_lowercase', 'digits'], length=32) }}'
some_other_option = 'yes'
这将为我们的配置文件提供所需的随机字符串,但我试图避免的问题是它将来会发生变化(例如,如果我们将来将
some_other_option
更改为
no
)。 因此,我想找到一种方法,仅在首次配置文件时才替换 Jinja2 变量。
如何有条件地替换 Jinja2 变量,使其在后续运行中永远不会更改,无需维护 ansible 控制器的状态?
问:
A:你的问题归结为“控制器如何知道这是第一次?”。有很多选择:
获取文件的状态
- stat:
path: /tmp/my-service.conf
register: msconf
ms:
user: "{{ user | d('admin') }}"
some_other_option: "{{ some_other_option | d('yes') }}"
并在模板中使用它们
user = '{{ ms.user }}'
password = '{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_lowercase', 'digits'], length=32) }}'
some_other_option = '{{ ms.some_other_option }}'
如果文件不存在则创建该文件
- template:
src: my-service.conf.j2
dest: /tmp/my-service.conf
when: not msconf.stat.exists
例如给出
shell> cat /tmp/my-service.conf
user = 'admin'
password = '47ittk4konkg23ywg3kolim7sswuavzs'
some_other_option = 'yes'
使用模块
community.general.ini_file如果文件存在
- community.general.ini_file:
path: /tmp/my-service.conf
option: "{{ item.key }}"
value: "'{{ item.value }}'"
loop: "{{ ms | dict2items }}"
when: msconf.stat.exists
任务是幂等的。在您更改字典之前,什么都不会改变。例如,如果您设置
some_other_option='no'
,文件将会更改
TASK [community.general.ini_file] ***********************************************************************************
ok: [test_11] => (item={'key': 'user', 'value': 'admin'})
changed: [test_11] => (item={'key': 'some_other_option', 'value': 'no'})
shell> cat /tmp/my-service.conf
user = 'admin'
password = '47ittk4konkg23ywg3kolim7sswuavzs'
some_other_option = 'no'
用于测试的完整游戏示例
- hosts: test_11
vars:
ms:
user: "{{ user | d('admin') }}"
some_other_option: "{{ some_other_option | d('yes') }}"
tasks:
- stat:
path: /tmp/my-service.conf
register: msconf
- template:
src: my-service.conf.j2
dest: /tmp/my-service.conf
when: not msconf.stat.exists
- community.general.ini_file:
path: /tmp/my-service.conf
option: "{{ item.key }}"
value: "'{{ item.value }}'"
loop: "{{ ms | dict2items }}"
when: msconf.stat.exists