如何在 Ansible 中使用带有 dict 元素的 jinja2 模板生成 CSV 文件?

问题描述 投票:0回答:1

我正在尝试使用以下模板生成 CSV 输出文件: 主机名;登录;UID;GID;评论;SUDO 启用;Last_Login_Date

此任务必须根据 /etc/passwd 中的信息检查 UID >= 1000 的每个用户的此信息。注释与 /etc/passwd 中的注释字段相同。如果用户具有 SUDO 权限,则必须仅显示 YES 或 NO。对于 Last_Login_Date,如果用户从未登录过该系统,则应显示 N/A。

对于此任务,我提供了 Ansible playbook 解决方案,但我不知道如何在创建 CSV 文件时修复以下错误。

剧本:

  tasks:
    - name: Check User List
      shell:
        cmd: |
           awk -F ':' '{ if ($3 >= 999 && $7 != "/sbin/nologin") print $1 }' /etc/passwd
      register: user_list_result

    - name: Get info on /etc/passwd
      ansible.builtin.shell: "grep ^{{ item }}: /etc/passwd"
      loop: "{{ user_list_result.stdout_lines }}"
      register: user_info_results

    - name: Check SUDO Privileges
      ansible.builtin.shell: "sudo -U {{ item.item }} -l | grep -q '(ALL) ALL' && echo 'YES' || echo 'NO'"
      loop: "{{ user_info_results.results }}"
      register: sudo_status_results

    - name: Check Last Login Date
      ansible.builtin.shell: "lastlog -u {{ item.item }} | awk 'NR==2 { print $4 }'"
      loop: "{{ user_info_results.results }}"
      register: last_login_results

    - name: Build CSV File
      ansible.builtin.template:
        src: "userlist_template.j2"
        dest: "output.csv"
      vars:
        user_info_results: "{{ user_info_results.results }}"
        sudo_status_results: "{{ sudo_status_results.results }}"
        last_login_results: "{{ last_login_results.results }}"

我来到了这个 Jinja2 模板:

Hostname;Login;UID;GID;Comments;SUDO Enabled;Last_Login_Date
{% for user_info in user_info_results %}
{{ inventory_hostname }};{{ user_info['item'] }};{{ user_info.stdout.split(':')[2] }};{{ user_info.stdout.split(':')[3] }};{{ user_info.stdout.split(':')[4] }};{{ sudo_status_results[loop.index0].stdout }};{{ last_login_results[loop.index0].stdout | default('N/A') }}
{% endfor %}

但是当我运行此剧本时,出现以下错误:

The error was: ansible.errors.AnsibleUndefinedVariable: 'str object' has no attribute 'item'

Ansible 似乎正在检查字符串对象,但它是一个 dict 对象。我怎样才能实现建议的文件?

linux csv ansible jinja2
1个回答
0
投票

首先,如果你不是 Mac OS,我建议你使用

getent
模块而不是手动解析文件。

现在介绍模板结构。如果我们出于调试目的对其进行简化,我们会发现

user_info_results
变量似乎没有您期望的结构:

Hostname;Login;UID;GID;Comments;SUDO Enabled;Last_Login_Date
{% for user_info in user_info_results %}
{{ inventory_hostname }};{{ user_info }}
{% endfor %}
Hostname;Login;UID;GID;Comments;SUDO Enabled;Last_Login_Date
localhost;results;
localhost;skipped;
localhost;changed;
localhost;msg;

因此,使用变量的嵌套

results
对象可以修复模板:

Hostname;Login;UID;GID;Comments;SUDO Enabled;Last_Login_Date
{% for user_info in user_info_results.results %}
{{ inventory_hostname }};{{ user_info['item'] }};{{ user_info.stdout.split(':')[2] }};{{ user_info.stdout.split(':')[3] }};{{ user_info.stdout.split(':')[4] }};{{ sudo_status_results.results[loop.index0].stdout }};{{ last_login_results.results[loop.index0].stdout | default('N/A') }}
{% endfor %}

我将 UID 减少到 280 进行测试,因为我本地没有任何 UID >= 1000:

Hostname;Login;UID;GID;Comments;SUDO Enabled;Last_Login_Date
localhost;_coreml;280;280;CoreML Services;NO;
localhost;_sntpd;281;281;SNTP Server Daemon;NO;
localhost;_trustd;282;282;trustd;NO;
localhost;_darwindaemon;284;284;Darwin Daemon;NO;
localhost;_notification_proxy;285;285;Notification Proxy;NO;
localhost;_oahd;441;441;OAH Daemon;NO;

为什么会发生这种情况?虽然看起来有点令人惊讶,但有记录: 注册变量的优先级高于任务变量

© www.soinside.com 2019 - 2024. All rights reserved.