如何将主机与ansible中的变量配对

问题描述 投票:0回答:2

我有一个库存,例如:

all:
  children:
    server_group1:
      hosts:
        host1:
    server_group2:
      children:
        app1:
          hosts:
            host2:
            host3:
        app2:
          hosts:
            host4:
            host5:
    server_group3:
...

我已经像这样组织了我的服务器变量:

> cat group_vars/server_group2/app1
app1:
  name1: value1
  name2: value2

> cat group_vars/server_group2/app2
app2:
  name1: value11
  name2: value21

我试图以该组的名字命名我的字典(从而使它们独一无二)并在我的剧本中访问它:

hosts: server_group2
tasks:
  - name: check file
    local_action: stat path=path/to/test/{{hostvars[0].name1}}
    register: payld_txt

  - name: conditional transfer
    copy:
      src: path/to/test/{{hostvars[0].name1}}
      dest: /svr/path/{{hostvars[0].name2}}
    when: payld_txt.stat.exists

我最终遇到了这个错误: 该任务包含一个带有未定义变量的选项。错误是:“name1”未定义

我哪里出错了?

ansible ansible-inventory
2个回答
5
投票

在继续之前,您需要修复不尊重 yaml 源的 ansible 结构的清单。下面一个简单的命令可以给你一些提示:

$ ansible -i inventories/test.yml all --list-hosts
 [WARNING]: Skipping unexpected key (server_group1) in group (all), only "vars", "children" and "hosts" are valid

 [WARNING]: Skipping unexpected key (server_group2) in group (all), only "vars", "children" and "hosts" are valid

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

  hosts (0):

正确的语法是:

---
all:
  children:
    server_group1:
      hosts:
        host1:
    server_group2:
      children:
        app1:
          hosts:
            host2:
            host3:
        app2:
          hosts:
            host4:
            host5:

现在给出:

$ ansible -i inventories/test.yml all --list-hosts
  hosts (5):
    host1
    host2
    host3
    host4
    host5

2
投票
``hostvars[0].name1`` The error was: 'name1' is undefined

问:“我哪里出错了?”

A:变量

name1
是字典
app1
app2
的项目。必须引用
app1.name1
app2.name1
。除此之外,
hostvars
是字典而不是数组。
hostvars[0]
不存在。字典的项目必须由键引用。比如下面这个剧

- hosts: server_group2
  tasks:
    - set_fact:
        my_keys: "{{ hostvars.keys()|list }}"
      run_once: true
    - debug:
        var: my_keys
      run_once: true
    - debug:
        msg: "{{ hostvars[item].app1.name1 }}"
      loop: "{{ my_keys }}"
      when: "item in groups['app1']"
      run_once: true
    - debug:
        msg: "{{ hostvars[item].app2.name1 }}"
      loop: "{{ my_keys }}"
      when: "item in groups['app2']"
      run_once: true

给予

ok: [host5] => 
  my_keys:
  - host5
  - host4
  - host3
  - host2
  - host1

ok: [host5] => (item=host3) => 
  msg: value1
ok: [host5] => (item=host2) => 
  msg: value1

ok: [host5] => (item=host5) => 
  msg: value11
ok: [host5] => (item=host4) => 
  msg: value11

可以选择使用 json_query 创建键列表

 - set_fact:
     my_keys: "{{ hostvars|dict2items|json_query('[].key') }}"
   run_once: true

剧本的简化版

- hosts: server_group2
  tasks:
    - debug:
        msg: "{{ hostvars[inventory_hostname].app1.name1 }}"
      when: "inventory_hostname in groups['app1']"
    - debug:
        msg: "{{ hostvars[inventory_hostname].app2.name1 }}"
      when: "inventory_hostname in groups['app2']"

给予

skipping: [host5]
skipping: [host4]
ok: [host3] => 
  msg: value1
ok: [host2] => 
  msg: value1

ok: [host5] => 
  msg: value11
ok: [host4] => 
  msg: value11
skipping: [host3]
skipping: [host2]

事实上,解决

hostvars[inventory_hostname]
是没有必要的。下面的简化任务给出相同的输出。

- debug:
    msg: "{{ app1.name1 }}"
  when: "inventory_hostname in groups['app1']"
- debug:
    msg: "{{ app2.name1 }}"
  when: "inventory_hostname in groups['app2']"
© www.soinside.com 2019 - 2024. All rights reserved.