Jinja2 循环内的未定义变量 - 试图访问索引
Undefined variable inside Jinja2 loop - trying to access an index
我有一个主剧本,运行还有另外 3 个剧本作为我的用户终止流程的一部分。这是手册:
---
- name: "Playbook: Terminate user"
hosts: localhost
gather_facts: True
roles:
- { role: common, tags: ['always'] }
- { role: terminate_user, tags: ['terminate_user', 'never'] }
- name: "Playbook: Terminate storage"
hosts: storage
gather_facts: False
roles:
- { role: terminate_storage, tags: ['terminate_storage', 'always'] }
- name: "Playbook: User environment"
hosts: localhost
gather_facts: False
roles:
- { role: common,
tags: ['always'],
}
- { role: send_email,
tags: ['send_email', 'always']
}
我正在尝试在我的 send_email
剧本中打印出 storage
剧本的输出。它看起来像这样:
- name: Logical block of home-storage tasks
block:
- name: Check if home folder exists
stat:
path: "{{ hostvars[inventory_hostname].fspath }}/{{ username }}"
register: home_dir_details
- name: Move user home folder to terminated home folder
command: mv {{ hostvars[inventory_hostname].fspath }}/{{ username }} "{{ hostvars[inventory_hostname].fspath }}/terminated/{{ username }}"
when: home_dir_details.stat.exists
register: storage_moved
- name: Printing and debugging
ansible.builtin.debug:
msg: "{{ storage_moved }}"
when:
- hostvars[inventory_hostname].fsname is search("home")
在电子邮件模板中,我正在打印 storage_moved
变量,如下所示:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved'] }}
{% endfor %}
输出看起来不错,这正是我在 playbook 中看到的 运行(第一个被故意跳过):
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'}
{'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
在我的 storage
主机中,我只配置了 2 个服务器,所以打印 2 个字典看起来没问题。
我的问题是,当我尝试访问 cmd
变量时,我无法访问或不知道如何访问。例如,我认为这应该有效:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved'][loop.index] }}
{% endfor %}
我得到一个错误:"msg": "The task includes an option with an undefined variable. The error was: dict object has no element 1
所以我尝试了这样的事情:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] }}
{% endfor %}
但效果不佳,出现以下错误:"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'cmd'
。
我不确定应该如何访问该变量。
抱歉,误读了您的问题。让我再试一次。 :) 在您的示例中,您提供以下内容:
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'}
{'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
您的第一个结果记录了一个跳过的任务,因此字典不包含 cmd
键。
试试改成这样:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] | default('skipped') }}
{% endfor %}
default
过滤器将在指定变量未定义的情况下提供一个值。这会改善情况吗?
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'}
{'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
仔细查看示例循环中的第一个输出结果,即从跳过的任务返回的结果:您是否在任何地方看到 cmd
属性?那么,答案是:没有。所以你报告的错误实际上是预期的。
您需要管理您要查找的属性不存在的情况。一种简单的解决方案是提供默认值,但您可以根据自己的具体要求找到自己的默认值。
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] | default('No command was played') }}
{% endfor %}
我有一个主剧本,运行还有另外 3 个剧本作为我的用户终止流程的一部分。这是手册:
---
- name: "Playbook: Terminate user"
hosts: localhost
gather_facts: True
roles:
- { role: common, tags: ['always'] }
- { role: terminate_user, tags: ['terminate_user', 'never'] }
- name: "Playbook: Terminate storage"
hosts: storage
gather_facts: False
roles:
- { role: terminate_storage, tags: ['terminate_storage', 'always'] }
- name: "Playbook: User environment"
hosts: localhost
gather_facts: False
roles:
- { role: common,
tags: ['always'],
}
- { role: send_email,
tags: ['send_email', 'always']
}
我正在尝试在我的 send_email
剧本中打印出 storage
剧本的输出。它看起来像这样:
- name: Logical block of home-storage tasks
block:
- name: Check if home folder exists
stat:
path: "{{ hostvars[inventory_hostname].fspath }}/{{ username }}"
register: home_dir_details
- name: Move user home folder to terminated home folder
command: mv {{ hostvars[inventory_hostname].fspath }}/{{ username }} "{{ hostvars[inventory_hostname].fspath }}/terminated/{{ username }}"
when: home_dir_details.stat.exists
register: storage_moved
- name: Printing and debugging
ansible.builtin.debug:
msg: "{{ storage_moved }}"
when:
- hostvars[inventory_hostname].fsname is search("home")
在电子邮件模板中,我正在打印 storage_moved
变量,如下所示:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved'] }}
{% endfor %}
输出看起来不错,这正是我在 playbook 中看到的 运行(第一个被故意跳过):
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'}
{'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
在我的 storage
主机中,我只配置了 2 个服务器,所以打印 2 个字典看起来没问题。
我的问题是,当我尝试访问 cmd
变量时,我无法访问或不知道如何访问。例如,我认为这应该有效:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved'][loop.index] }}
{% endfor %}
我得到一个错误:"msg": "The task includes an option with an undefined variable. The error was: dict object has no element 1
所以我尝试了这样的事情:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] }}
{% endfor %}
但效果不佳,出现以下错误:"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'cmd'
。
我不确定应该如何访问该变量。
抱歉,误读了您的问题。让我再试一次。 :) 在您的示例中,您提供以下内容:
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'}
{'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
您的第一个结果记录了一个跳过的任务,因此字典不包含 cmd
键。
试试改成这样:
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] | default('skipped') }}
{% endfor %}
default
过滤器将在指定变量未定义的情况下提供一个值。这会改善情况吗?
{'changed': False, 'skipped': True, 'skip_reason': 'Conditional result was False'} {'changed': True, 'end': '2021-10-21 12:47:13.363691', 'stdout': '', 'cmd': ['mv', '/path/user', '/path/terminated/user'], 'rc': 0, 'start': '2021-10-21 12:47:13.357842', 'stderr': '', 'delta': '0:00:00.005849', 'stdout_lines': [], 'stderr_lines': [], 'failed': False}
仔细查看示例循环中的第一个输出结果,即从跳过的任务返回的结果:您是否在任何地方看到 cmd
属性?那么,答案是:没有。所以你报告的错误实际上是预期的。
您需要管理您要查找的属性不存在的情况。一种简单的解决方案是提供默认值,但您可以根据自己的具体要求找到自己的默认值。
{% for host in groups['storage'] %}
{{ hostvars[host]['storage_moved']['cmd'] | default('No command was played') }}
{% endfor %}