Ansible任务中向vars传入字典报错问题排查
Ansible import_role 传参报错排查
我使用Ansible [core 2.16.6]编写了如下代码,通过set_fact生成字典类型变量pgs_server_custom_role_vars,debug验证其为字典且内容正确,但在import_role的vars字段传入该变量时,却报错提示“Vars in a IncludeRole must be specified as a dictionary”。请问这是Bug还是操作有误?
代码示例
- name: Install and configure PGS servers for RZ hosts: pgs_rzdb_servers tasks: - name: Prepare pgs_server role variables set_fact: pgs_server_custom_role_vars: >- {{ { 'pgs_server_version': pgs_rzdb_server_version, 'pgs_server_port': pgs_rzdb_server_port, 'pgs_server_pg_hba_rules': pgs_rzdb_server_pg_hba_rules, 'pgs_server_max_connections': pgs_rzdb_server_max_connections, 'pgs_server_idle_in_transaction_session_timeout': pgs_rzdb_server_idle_in_transaction_session_timeout, 'pgs_server_marker': 'RZDB' } | dict2items | selectattr('value', 'defined') | items2dict }} - debug: msg: "Role variables: {{ pgs_server_custom_role_vars }}" - debug: msg: "Role variables: {{ pgs_server_custom_role_vars | type_debug }}" - name: pgs_server import_role: name: pgs_server vars: "{{ pgs_server_custom_role_vars }}" tags: - pgs_server
Debug输出
TASK [debug] ************************************************************************************************************************************************************************************************************************************** ok: [lspostgres02.ls.local] => { "msg": "Role variables: {'ls_pgs_server_version': 13, 'ls_pgs_server_port': 5431, 'ls_pgs_server_pg_hba_rules': [{'contype': 'host', 'users': 'all', 'source': 'lxserver.ls.local', 'databases': 'all', 'method': 'md5'}, {'contype': 'host', 'users': 'all', 'source': '192.168.69.0/24', 'databases': 'all', 'method': 'md5'}], 'ls_pgs_server_marker': 'RZDB'}" } TASK [debug] ************************************************************************************************************************************************************************************************************************************** ok: [lspostgres02.ls.local] => { "msg": "Role variables: dict" }
报错信息
ERROR! Vars in a IncludeRole must be specified as a dictionary The error appears to be in '/mnt/c/Users/dhe/Documents/Checkouts/ls-ansible/ls_pgs_rzdb_servers.yml': line 30, column 13, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: name: pgs_server vars: "{{ pgs_server_custom_role_vars }}" ^ here We could be wrong, but this one looks like it might be an issue with missing quotes. Always quote template expression brackets when they start a value. For instance: with_items: - {{ foo }} Should be written as: with_items: - "{{ foo }}"
问题分析与解决
这不是Bug,是操作有误,核心原因是**import_role与set_fact的执行时机不匹配**:
根本原因
import_role属于Ansible的静态导入模块,会在playbook解析阶段就处理所有参数(包括vars字段);而set_fact是在playbook运行阶段才会创建变量pgs_server_custom_role_vars。
也就是说,当Ansible解析import_role的vars参数时,目标变量还未被生成,此时Ansible无法识别出它是字典类型,因此抛出错误。而debug任务是运行阶段执行的,此时变量已经存在,所以能正常显示内容。
解决方法
有两种可行的修复方案:
方案1:改用动态导入的include_role
include_role是运行阶段处理的模块,能正确获取到set_fact生成的变量,修改后的代码如下:
- name: pgs_server include_role: name: pgs_server vars: "{{ pgs_server_custom_role_vars }}" tags: - pgs_server
方案2:提前在解析阶段定义变量
如果必须使用import_role,可以把变量生成逻辑移到play的vars部分(解析阶段处理),确保import_role能在解析时获取到变量:
- name: Install and configure PGS servers for RZ hosts: pgs_rzdb_servers vars: pgs_server_custom_role_vars: >- {{ { 'pgs_server_version': pgs_rzdb_server_version, 'pgs_server_port': pgs_rzdb_server_port, 'pgs_server_pg_hba_rules': pgs_rzdb_server_pg_hba_rules, 'pgs_server_max_connections': pgs_rzdb_server_max_connections, 'pgs_server_idle_in_transaction_session_timeout': pgs_rzdb_server_idle_in_transaction_session_timeout, 'pgs_server_marker': 'RZDB' } | dict2items | selectattr('value', 'defined') | items2dict }} tasks: - debug: msg: "Role variables: {{ pgs_server_custom_role_vars }}" - debug: msg: "Role variables: {{ pgs_server_custom_role_vars | type_debug }}" - name: pgs_server import_role: name: pgs_server vars: "{{ pgs_server_custom_role_vars }}" tags: - pgs_server
内容的提问来源于stack exchange,提问作者henkesde92
相关产品推荐
相关产品推荐

