我怎样才能在不同的角色中保持一个可靠的变量?

How can I persist an ansible variable across ansible roles?

我在一个play里注册了一个变量

---
- hosts: 127.0.0.1
  gather_facts: no
  connection: local
  sudo: no
  vars_files:
    - vars.yml
  tasks:
    - name: build load balancer
      os_load_balancer: net=mc_net ext_net=vlan3320 name=load_balancer protocol=HTTPS port=80
      register: my_lb

我可以很好地访问该变量,直到我在角色内发出请求。

例如,在同一个单独的角色运行中,我想访问那个注册的变量:

- debug: var=my_lb

我得到以下输出:

{'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'my_lb' is undefined", 'failed': True}

如何在同一个游戏中访问在单独角色中注册的变量?

Edit for clarity of how things piece together:

Top Play
-includes: 
  - Sub play 1
    - registers variable foo
  - Sub play 2
    -includes:
      - sub play A
        - role 1 
        - role 2
        - role 3 
          - references variable foo in template
      - Sub play B
  - Sub play 3

如何将它作为参数传递给角色。我假设这样的(寄存器)变量没有隐式传递(就像 hotvars 一样)。

- { role: my_role, my_lb: "{{my_lb}}" }

尝试将您的变量声明移动到 pre_task 块中。此处设置的变量应在角色内和角色后可用。

https://docs.ansible.com/playbooks_roles.html#roles

例如

pre_tasks:
    - name: build load balancer
      os_load_balancer: net=mc_net ext_net=vlan3320 name=load_balancer protocol=HTTPS port=80
      register: my_lb

roles:
  - { role: some_role }

注意:这是参考 Ansible 1.X 编写的。我怀疑变量解析和作用域在 Ansible 2.0 中发生了很大变化,所以请记住这一点。如果我有时间,我会尝试更新答案(或者也许其他人会回答 v2.0!)

这里有两个选项。最简单的方法是在您的顶级剧本中定义变量,然后将它们传播到您的各种角色中。您可以将它们设置为简单的变量,或使用 pre_tasks 动态查找/计算值,例如

vars:
    foo_static: "value_bar"

pre_tasks:
    - set_fact:
        foo_ncpu: "{{ ansible_processor_vcpus }}"

  roles:
    - {role: role1, role1_var1: "{{foo_static}}", role1_var2: "{{foo_ncpu}}" }
    - {role: role2, role2_var1: "{{foo_static}}", role2_var2: "{{foo_ncpu}}" }

第二个选项要求您将任务添加到您需要从中提取变量的任何角色(尽管由于所有 ansible 角色都是开源的,这应该很容易)。诀窍是使用 set_fact 将变量导出为 'host_fact',例如

- name: Export role1_varfoo to a 'host-fact' type variable
  set_fact:
    role1_varfoo: "{{ role1_varfoo }}"

稍后可以像这样访问:

  vars:
    role2_varfoo: "{{ hostvars['myhost']['role1_varfoo']}}"

this bit of the ansible docs所述。

请注意,如果您总是想查找当前机器的主机变量,您正在执行 运行 命令(不知道它在 ansible hosts 文件中实际调用的是什么),您可以使用变量 inventory_hostname 像这样:

  vars:
    role2_varfoo: "{{ hostvars[inventory_hostname]['role1_varfoo']}}"

(注意缺少引号,因为它是一个变量,而不是字符串文字。)

有点尴尬,不过这些组合已经满足了我的所有需求。

Update: To access the variable using the hostvars syntax use the appropriate host GROUP variable rather than the host that executed the set_fact:

hostvars[inventory_hostname]['variable']

扩大已接受的问题。

1.-您可以在注册变量的地方定义另一个角色,然后在那里设置它,然后从多个角色引用该变量。只要角色在同一个剧中。 在这里记录: http://docs.ansible.com/ansible/playbooks_variables.html#variable-examples

Generally speaking, variables set in one role are available to others. This means if you have a roles/common/vars/main.yml you can set variables in there and make use of them in other roles and elsewhere in your playbook

编辑:澄清,根据我的经验,这适用于在 Ansible 2.x 中注册和设置变量。

2.-就使用 hostvars 而言,我自己尝试并失败并出现此错误:

fatal: [localhost]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'ec2_instance_id'"} 

我的情况是我正在执行以下操作。

- hosts: localhost
  gather_facts: yes
  roles:
  - { role: role_1 }
post_tasks:
- name: Check instance variables within localhost
  debug: var={{ hostvars['localhost']['ec2_instance_id'] }}

在角色 1 中我有:

- name: register instance_id
  set_fact: ec2_instance_id="{{ item.id }}"
  with_items: "{{ ec2_instance.instances }}"

虽然根据这个旧线程,hostvar 方法应该有效:

https://github.com/ansible/ansible/issues/1934