Ansible 模板:如果与现有文件没有区别,则跳过

Ansible template: Skip if there is no difference to existing file

提问人:yFStein 提问时间:10/9/2023 更新时间:10/9/2023 访问量:65

问:

实际上,我正在进入 Ansible 并编写我的第一本剧本,当我拿到它们时,它会在我的 Linux 服务器上进行一些常规设置。

我正在尝试应用 Jinja2 模板,但前提是该文件不存在或与 Jinja2 模板中的内容不同。如果文件内容相同,则应跳过该任务。

我已经有了跳过设置时区的行为:

  - name: Check current Timezone
    command: timedatectl show --property=Timezone --value
    register: timezone_output
    changed_when: false

  - name: Configure Timezone
    command: timedatectl set-timezone {{ timezone }}
    when: timezone_output.stdout != timezone

但是我无法得到这个来比较文件。我已经试过了 - 但是尽管文件的内容相同,但校验和并不相等:

---
- name: Calculate checksum of Jinja2 template
  set_fact:
    template_content: "{{ lookup('file', 'templates/sshd_config.j2') }}"

- name: Display checksum template
  debug:
    var: template_content | md5

- name: Calculate checksum of remote file
  command: md5sum /etc/ssh/sshd_config.d/initial.conf
  register: md5sum_output
  changed_when: false
  check_mode: no

- set_fact:
    remote_file_checksum: "{{ md5sum_output.stdout.split()[0] }}"
      
- name: Display checksum
  debug:
    var: remote_file_checksum

- name: Update SSH configuration
  template:
    src: sshd_config.j2
    dest: /etc/ssh/sshd_config.d/initial.conf
  notify: Reload SSH Service

由于我将有相当多的角色将应用模板,因此,如果文件的内容已经正确,那么跳过这些任务对我来说很重要,以便以后进行更好的评估。

Linux 服务器 比较 ansible-template

评论

3赞 Zeitounator 10/9/2023
你把这条路弄得太难了。该模块(与大多数 Ansible 模块一样)是完全幂等的。因此,如果不需要,它不会更改目标系统上的任何内容。因此,上面只需要您的最后一个任务。仅当文件不存在或与插值模板不同时,它才会报告“已更改”,在这种情况下,只会通知处理程序。如果内容已经是预期的内容,则任务将报告“正常”,并且不会有通知。template
0赞 yFStein 10/9/2023
然后我只是误解了它。感谢您的许可。

答:

2赞 Vladimir Botka 10/9/2023 #1

Zeitounator 的评论是成功使用模块模板所需的全部内容。让我解释一下为什么您会看到不同的校验和。

简短的回答:使用模板代替查找插件文件

详细信息:给定模板

shell> cat sshd_config.j2
Port: {{ sshd_Port }}
AddressFamily: {{ sshd_AddressFamily }}
ListenAddress: {{ sshd_ListenAddress4 }}
ListenAddress: {{ sshd_ListenAddress6 }}

和变量

sshd_Port: 22
sshd_AddressFamily: any
sshd_ListenAddress4: 0.0.0.0
sshd_ListenAddress6: '::'

以下任务

    - template:
        src: sshd_config.j2
        dest: /tmp/sshd_config

shell> cat /tmp/sshd_config 
Port: 22
AddressFamily: any
ListenAddress: 0.0.0.0
ListenAddress: ::

使用模板查找可以获得相同的结果

    - debug:
        msg: "{{ lookup('template', 'sshd_config.j2') }}"

  msg:
    Port: 22
    AddressFamily: any
    ListenAddress: 0.0.0.0
    ListenAddress: ::

但是,当您使用文件查找时

    - debug:
        msg: "{{ lookup('file', 'sshd_config.j2') }}"

变量不会展开

  msg:
    Port: {{ sshd_Port }}
    AddressFamily: {{ sshd_AddressFamily }}
    ListenAddress: {{ sshd_ListenAddress4 }}
    ListenAddress: {{ sshd_ListenAddress6 }}

  • 用于测试的完整 playbook 示例
- hosts: localhost

  vars:

    sshd_Port: 22
    sshd_AddressFamily: any
    sshd_ListenAddress4: 0.0.0.0
    sshd_ListenAddress6: '::'

  tasks:

    - debug:
        msg: "{{ lookup('template', 'sshd_config.j2') }}"

    - debug:
        msg: "{{ lookup('file', 'sshd_config.j2') }}"

    - template:
        src: sshd_config.j2
        dest: /tmp/sshd_config

如果要比较校验和,还有一个问题

    - debug:
        msg: |
          {{ lookup('template', 'sshd_config.j2')|md5 }}
          {{ lookup('file', '/tmp/sshd_config')|md5 }}
          {{ lookup('file', 'sshd_config.j2')|md5 }}

  msg: |-
    2ee29dc15e27ef8169fc557ea6e52263
    bfa2cb3f7cda847038b2591a6e07bbff
    6a91ff2707d18b5f397a03c8e6433b4e

前两项的校验和应相等。遗憾的是,模板查找会在结果中添加一个空行,但模块模板在创建文件时会删除此空行。如果要获得相同的校验和,请从模板查找结果中删除最后一个空行

    - debug:
        msg: |
          {{ tmpl|md5 }}
          {{ lookup('file', '/tmp/sshd_config')|md5 }}
          {{ lookup('file', 'sshd_config.j2')|md5 }}
      vars:
        tmpl: "{{ lookup('template', 'sshd_config.j2').splitlines()|join('\n') }}"

  msg: |-
    bfa2cb3f7cda847038b2591a6e07bbff
    bfa2cb3f7cda847038b2591a6e07bbff
    6a91ff2707d18b5f397a03c8e6433b4e