linux 如何将set_fact模块设置的变量传递给Jinja2模板?

roejwanj  于 2023-02-18  发布在  Linux
关注(0)|答案(1)|浏览(210)

我的角色是设置NATS群集,我使用host_vars定义哪个节点是主节点,如下所示:

is_master: true

然后在setup-nats.yml任务中,我使用以下代码根据我设置的host_var提取主节点的IP地址,然后将其用作Jinja2模板的变量,但是,该变量不会传递到模板,我得到的是"变量" master_ip "未定义。

- name: Set master IP
  set_fact:
    set_master_ip: "{{ ansible_facts['default_ipv4']['address'] }}"
    cacheable: yes
  when: is_master

- name: debug
  debug:
    msg: "{{ set_master_ip }}"
  run_once: true

- name: generate nats-server.conf for the slave nodes
  template:
    src: nats-server-slave.conf.j2
    dest: /etc/nats-server.conf
    owner: nats
    group: nats
    mode: 0644
  when:
    - is_master == false
  vars:
    master_ip: "{{ set_master_ip }}"
  notify: nats-server

变量在Jinja2模板中的用法如下:

routes = [
    nats-route://ruser:{{ nats_server_password }}@{{ master_ip }}:6222
  ]
}

问题:

  • 这种方法是否符合最佳做法?
  • 执行上述操作的正确方法是什么,以便将变量传递给模板?

测试输出:
我正在使用Molecule来测试我的Ansible,尽管在调试任务中IP地址是可见的,但它不会传递到模板:

TASK [nats : Set master IP] ****************************************************
ok: [target1]
skipping: [target2]
skipping: [target3]

TASK [nats : debug] ************************************************************
ok: [target1] => 
  msg: 10.0.2.15

TASK [nats : generate nats-server.conf for the slave nodes] ********************
skipping: [target1]
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.errors.AnsibleUndefinedVariable: {{ set_master_ip }}: 'set_master_ip' is undefined
fatal: [target2]: FAILED! => changed=false 
  msg: 'AnsibleUndefinedVariable: {{ set_master_ip }}: ''set_master_ip'' is undefined'
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.errors.AnsibleUndefinedVariable: {{ set_master_ip }}: 'set_master_ip' is undefined
fatal: [target3]: FAILED! => changed=false 
  msg: 'AnsibleUndefinedVariable: {{ set_master_ip }}: ''set_master_ip'' is undefined'

任何帮助都是感激的,提前感谢。
UPDATE:我怀疑这个问题与主机上下文中的变量作用域有关,但无法找到修复它的方法(尽管我可能错了)。

uajslkp6

uajslkp61#

这不是IMO的最佳实践,而是回答了你的直接问题。你的问题不是把变量传递给你的模板,而是它没有被分配给你的播放循环中的所有主机(因此在任何非主节点上都是未定义的)。下面(未经测试)解决了保持相同任务结构的问题。

- name: Set master IP for all nodes
  ansible.builtin.set_fact:
    master_ip: "{{ hostvars | dict2items | map(attribute='value'
      | selectattr('is_master', 'defined') | selectattr('is_master')
      | map(attribute='ansible_facts.default_ipv4.address') | first }}"
    cacheable: yes
  run_once: true

- name: Show calculated master IP (making sure it is assigned everywhere)
  ansible.builtin.debug:
    msg: "{{ master_ip }}"

- name: generate nats-server.conf for the slave nodes
  ansible.builtin.template:
    src: nats-server-slave.conf.j2
    dest: /etc/nats-server.conf
    owner: nats
    group: nats
    mode: 0644
  when: not is_master | bool
  notify: nats-server

改进意见(非详尽):

  • 根据清单中的组成员身份而不是主机属性选择主服务器。这使得收集IP更容易(例如master_ip: "{{ hostvars[groups.master | first].ansible_facts.default_ipv4.address }}"
  • 将ip设置为play var或直接在节点组的清单中设置,而不是在set_fact任务中设置。

相关问题