如何处理 Ansible 中现有/不存在的事实?

如何处理 Ansible 中现有/不存在的事实?

由于某些业务限制,出于库存目的,我编写了一个剧本,检索 resolv.conf + ntp.conf + timesyncd.conf 的内容,然后将检索到的内容写入 CSV 文件中。

从总体上看,这可能不是最佳做法,但我在每个检索文件内容的任务中都设置了一个事实,然后我按照自己的想法格式化数据,最后将它们写入 csv 中,如 data1;data2;data3;

我遇到了一些问题/疑问:

  • 如果文件不存在,Ansible 任务将失败并且不会转到下一个任务,我知道这是设计使然。为了防止这种情况,在检索任务时使用 failed_when/changed_when 条件是否是一个好的解决方案?
  • 在最后一个任务(“将结果写入...”)中,如何处理不存在的事实?目前,如果存在 3 个事实,则写入文件。如果 1/3 的事实不存在,但其他事实存在,则不会写入任何内容。非常感谢您的建议。剧本如下
---

- name: sys-check_conf_ntp_dns_net
  hosts: my_servers
  remote_user: my_user

  tasks:
    # RESOLV.CONF
    - name: Retrieve remote /etc/resolv.conf 
      ansible.builtin.slurp:
        src: /etc/resolv.conf
      register: resolv_conf

    - name: Format resolv_conf_fact data
      set_fact:
        resolv_conf_fact: "{{ (resolv_conf['content'] | b64decode) | regex_findall('\\s*nameserver\\s*(.*)') }}"

    # NTP.CONF
    - name: Retrieve remote /etc/ntp.conf 
      ansible.builtin.slurp:
        src: /etc/ntp.conf
      register: ntp_conf

    - name: Format ntp_conf_fact data
      set_fact:
        ntp_conf_fact: "{{ (ntp_conf['content'] | b64decode) | regex_findall('(\\nserver.*?)(\\n)') }}"

    # TIMESYNCD.CONF
    - name: Retrieve /etc/systemd/timesyncd.conf 
      ansible.builtin.slurp:
        src: /etc/systemd/timesyncd.conf
      register: timesyncd_conf

    - name: Format timesyncd_conf_fact data
      set_fact:
        timesyncd_conf_fact: "{{ (timesyncd_conf['content'] | b64decode) | regex_search('(NTP=f.*)') }}"

    - name: Write results to /tmp/sys-check_conf_ntp_dns_net.csv
      lineinfile:
        path: /tmp/sys-check_conf_ntp_dns_net.csv
        line: "Hostname:{{inventory_hostname}};resolv.conf:{{ resolv_conf_fact }};ntp.conf:{{ ntp_conf_fact }};timesyncd.conf:{{ timesyncd_conf_fact }};"
        create: yes
      delegate_to: localhost

编辑

我终于找到了解决办法,不确定它是否合法:D对于我设置的每个事实,我都添加一个默认值,然后当它通过正则表达式进行过滤时,它的行为就像事实不为空一样,所以最后似乎起作用了。

例如 :

先设定一个事实:

ntp_conf_fact: "{{ (ntp_conf['content'] | b64decode) | regex_findall('(\\nserver.*?)(\\n)') }}"

确定事实后:

ntp_conf_fact: "{{ ((ntp_conf['content']|default([blabla])) | b64decode) | regex_findall('(\\nserver.*?)(\\n)') }}"

有人可以确认这听起来是否正确吗?或者是否有人有不同的解决方案?

答案1

使用default

您的方法default绝对正确,而且可行。

您不需要放置所有括号,您可以简单地将其写成:

{{ ntp_conf['content'] | default('') | b64decode | regex_findall('(\\nserver.*?)(\\n)') }}

如果文件不存在,slurp 会失败

slurp如果文件不存在则会失败,其后果是执行被中断failed

示例输出:

TASK [Retrieve remote /etc/resolv.conf] ************************************************************
ok: [server1]

TASK [Format resolv_conf_fact data] ****************************************************************
ok: [server1]

TASK [Retrieve remote /etc/ntp.conf] ***************************************************************
fatal: [server1]: FAILED! => {"changed": false, "msg": "file not found: /etc/ntp.conf"}

PLAY RECAP *****************************************************************************************
server1     : ok=2    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

ignore_errors: true为了防止这种情况,您应该在任务中添加slurp。这样,如果发生错误,它将被忽略并继续执行。您可以按照上面描述的方法使用来处理此异常default

NTP 任务示例:

- name: Retrieve remote /etc/ntp.conf
  ansible.builtin.slurp:
    src: /etc/ntp.conf
  ignore_errors: true
  register: ntp_conf

使用set_fact或执行任务vars

读取数据并将其存储在变量中set_fact没有任何问题,并且可以通过这种方式实现。

注意:如果通过 存储值到变量中set_fact,则这些值可用于所有后续任务,直到运行结束(只要不被覆盖),并可用于任意数量的任务。这同样适用于 存储的数据register:

如果您需要在“写入结果”任务中仅存储一次数据set_fact,则可以在相应的任务中直接定义变量,而无需制定单独的set_fact任务。

注意:在任务中使用 定义的变量vars:只在该任务内有效且可用,即它们在该任务范围内。

你的剧本可以是这样的:

---

- name: sys-check_conf_ntp_dns_net
  hosts: my_servers
  remote_user: my_user

  tasks:
    # RESOLV.CONF
    - name: Retrieve remote /etc/resolv.conf
      ansible.builtin.slurp:
        src: /etc/resolv.conf
      ignore_errors: true
      register: resolv_conf

    # NTP.CONF
    - name: Retrieve remote /etc/ntp.conf
      ansible.builtin.slurp:
        src: /etc/ntp.conf
      ignore_errors: true
      register: ntp_conf

    # TIMESYNCD.CONF
    - name: Retrieve /etc/systemd/timesyncd.conf
      ansible.builtin.slurp:
        src: /etc/systemd/timesyncd.conf
      ignore_errors: true
      register: timesyncd_conf

    - name: Write results to /tmp/sys-check_conf_ntp_dns_net.csv
      lineinfile:
        path: /tmp/sys-check_conf_ntp_dns_net.csv
        line: "Hostname:{{inventory_hostname}};resolv.conf:{{ resolv }};ntp.conf:{{ ntp }};timesyncd.conf:{{ timesyncd }};"
        create: yes
      vars:
        resolv: "{{ resolv_conf['content'] | default('') | b64decode | regex_findall('\\s*nameserver\\s*(.*)') }}"
        ntp: "{{ ntp_conf['content'] | default('') | b64decode | regex_findall('(\\nserver.*?)(\\n)') }}"
        timesyncd: "{{ timesyncd_conf['content'] | default('') | b64decode | regex_search('(NTP=f.*)') }}"
      delegate_to: localhost

如果数据仅需要一次,则使用的vars:优点是可以加速整个剧本的执行,因为任务数量减少了。

相关内容