在游戏之间共享 ansible 变量

Syn*_*hro 6 amazon-ec2 ansible

这是对这个问题的跟进。

我有一个配置一堆 EC2 实例的游戏。根据需要,该hosts值为localhost(因为当它运行时没有主机),并且 play 组装一个名为 的新主机列表ec2hosts,并生成一个主机 ip 到主机名映射,因为这是该信息第一次也是唯一一次可用,并且使用set_fact. 这个主机列表然后是后续播放的主题。问题是我需要hostname_map在第二个播放中使用配置播放期间创建的字典,我看不到如何执行此操作。

这是第一场比赛:

- hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    - name: Provision a set of instances
      ec2:
        key_name: marcus
        instance_type: t2.micro
        image: "{{ ami_id }}"
        wait: true
        exact_count: "{{ server_count }}"
        count_tag:
          Tutorial: "{{ tutorial_name }}"
        instance_tags:
          Tutorial: "{{ tutorial_name }}"
        groups: ['SSH', 'Web']
      register: ec2

    - name: Add all instance public IPs to host group
      add_host:
        hostname: "{{ item.public_ip }}"
        groups: ec2hosts
      loop: "{{ ec2.instances }}"

    - name: Build an IP to hostname map
      set_fact:
        hostname_map: "{{ hostname_map | combine({item.0.public_ip: (item.1 + '.' + tutorial_domain)}) }}"
      loop: "{{ ec2.instances|zip(hostnames)|list }}"

    - name: Debug hostname_map
      debug:
        msg: "{{ hostname_map }}"
Run Code Online (Sandbox Code Playgroud)

最后,hostname_map包含一个地图,如:

{
    "18.184.109.70": "host1.example.com", 
    "18.196.135.59": "host2.example.com"
}
Run Code Online (Sandbox Code Playgroud)

通过阅读有关变量范围的 ansible 文档,它说在剧中定义的变量在该剧之外不可用,除非它被应用于同一组主机。在这种情况下这是不可能的,所以我需要使用一个具有全局作用域的 var,从我读过set_fact的内容来看,这是做到这一点的合适方法。所以我在 中创建了一个空变量/group_vars/all,以便所有游戏都可以访问该变量:

hostname_map: {}
Run Code Online (Sandbox Code Playgroud)

下一个播放连接到每个新创建的实例(使用我们动态创建的主机列表)并从内部设置其主机名:

- hosts: ec2hosts
  gather_facts: yes
  tasks:
    - name: Debug hostname_map
      debug:
        msg: "{{ hostname_map }}"
    - name: Set hostnames
      hostname:
        name: "{{ hostname_map[ansible_host] }}"
Run Code Online (Sandbox Code Playgroud)

但是,这失败了,因为它hostname_map是空的

TASK [Debug hostname_map]
ok: [18.184.109.70] => {
    "msg": {}
}
ok: [18.196.135.59] => {
    "msg": {}
}
Run Code Online (Sandbox Code Playgroud)

所以我收到这个错误:

致命:[18.184.109.70]:失败!=> {"msg": "该任务包含一个带有未定义变量的选项。错误是:'dict object' 没有属性 u'18.184.109.70'

奇怪的是,即使我没有在 global 中定义变量,我也会得到相同的调试输出和错误。

我读过的其他文章都建议应该在 中显式枚举值vars,但我不能这样做,因为数据是动态的并且直到运行时才知道。同样,extra_vars出于同样的原因,我无法在命令行上使用它来提供它。

如何在第二场比赛中使这个变量可用?我想避免笨拙的解决方案,例如写出本地文件然后再读入!

我也愿意接受以完全不同的方式执行此操作的建议,其中“此”是:创建任意数量的 EC2 实例并为它们分配从静态列表中获取的主机名。

Zor*_*che 14

您设置的值set_fact将在不同的播放之间可用。请记住, set_fact 是为特定主机设置的。您的第一个游戏是针对localhost运行的,因此事实是 localhosts 变量的一部分。因此,在接下来的比赛中,您应该可以通过这样的任务访问它。

- debug:
    var: hostvars['localhost']['hostmap']
Run Code Online (Sandbox Code Playgroud)