英文:
Ansible : Select inventory file out of multiple hosts.ini for three environments based on the version passed as a variable
问题
我有一个任务,在这个任务中,我需要从放置在inventories/目录下不同文件夹中的多个清单文件中选择目标环境/主机。选择是基于作为变量传递的版本。
inventories/
preprod/
group_vars/
hosts.ini
...
systest/
group_vars/
hosts.ini
...
uat/
group_vars/
hosts.ini
...
因此,如果版本变量是1.x.x,则应选择preprod下的hosts.ini;如果是2.x.x,则应选择systest下的hosts.ini;如果是3.x.x,则应选择uat下的hosts.ini。
---
- name: 根据传递的版本从多个清单中选择主机
hosts: all
vars:
version: '1.0'
tasks:
- name: 从第一个清单获取主机
set_fact:
hosts_1: "{{ groups['inventory_1'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
- name: 从第二个清单获取主机
set_fact:
hosts_2: "{{ groups['inventory_2'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
- name: 合并来自两个清单的主机
set_fact:
hosts: "{{ hosts_1 + hosts_2 }}"
- name: 使用主机运行任务
debug:
msg: "{{ item }}"
loop: "{{ hosts }}"
英文:
I have a task , in which I need to select the target environment/hosts amongst the multiple inventory files placed in different folders under inventories/ directory. The selection is based on the version passed as a variable.
inventories/
preprod/
group_vars/
hosts.ini
...
systest/
group_vars/
hosts.ini
...
uat/
group_vars/
hosts.ini
...
So if the version varaiable is 1.x.x then the hosts.ini under preprod should be selected, if its 2.x.x then the hosts.ini under systest should be selected and if its 3.x.x the hosts.ini under uat should be selected.
---
- name: Select hosts from multiple inventories based on version passed as a variable
hosts: all
vars:
version: '1.0'
tasks:
- name: Get hosts from first inventory
set_fact:
hosts_1: "{{ groups['inventory_1'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
- name: Get hosts from second inventory
set_fact:
hosts_2: "{{ groups['inventory_2'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
- name: Merge hosts from both inventories
set_fact:
hosts: "{{ hosts_1 + hosts_2 }}"
- name: Run tasks with hosts
debug:
msg: "{{ item }}"
loop: "{{ hosts }}"
答案1
得分: 2
短回答:在第一个任务中复制清单文件,refresh_inventory,并在第二个任务中使用。不幸的是,这不会从目录中刷新 group_vars。作为解决方法,将 group_vars 放入清单文件中。
详细信息:给定用于测试的项目
shell> tree .
.
├── ansible.cfg
├── hosts.env
├── inventory
│   ├── preprod
│   │   └── hosts.ini
│   ├── systest
│   │   └── hosts.ini
│   └── uat
│   └── hosts.ini
└── pb.yml
4 directories, 6 files
将 group_vars 放入清单文件
shell> cat inventory/preprod/hosts.ini
[all]
preprod1
preprod2
preprod3
[all:vars]
env_gv=preprod
shell> cat inventory/systest/hosts.ini
systest1
systest2
systest3
[all:vars]
env_gv=systest
shell> cat inventory/uat/hosts.ini
[all]
uat1
uat2
uat3
[all:vars]
env_gv=uat
playbook
shell> cat pb.yml
- hosts: localhost
vars:
envs:
1: preprod
2: systest
3: uat
env: "{{ envs[version.split('.').0|int] }}"
tasks:
- debug:
msg: "Use environment: {{ env }}"
- copy:
src: "{{ playbook_dir }}/inventory/{{ env }}/hosts.ini"
dest: "{{ playbook_dir }}/hosts.env"
- meta: refresh_inventory
- hosts: all
tasks:
- block:
- debug:
var: ansible_play_hosts_all
- debug:
var: env_gv
run_once: true
给出
<sup>
version=1.0 在环境 preprod 中运作
shell> ansible-playbook -i hosts.env -e version=1.0 pb.yml
PLAY [localhost] ****************************************************************************************
TASK [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: preprod'
TASK 点击复制 *********************************************************************************************
changed: [localhost]
TASK [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
TASK [debug] ********************************************************************************************
ok: [preprod1] =>
ansible_play_hosts_all:
- preprod1
- preprod2
- preprod3
TASK [debug] ********************************************************************************************
ok: [preprod1] =>
env_gv: preprod
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
preprod1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
version=2.0 在环境 systest 中运作
shell> ansible-playbook -i hosts.env -e version=2.0 pb.yml
PLAY [localhost] ****************************************************************************************
任务 [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: systest'
任务 点击复制 *********************************************************************************************
changed: [localhost]
任务 [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
任务 [debug] ********************************************************************************************
ok: [systest1] =>
ansible_play_hosts_all:
- systest1
- systest2
- systest3
任务 [debug] ********************************************************************************************
ok: [systest1] =>
env_gv: systest
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
systest1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
version=3.0 在环境 uat 中运作
shell> ansible-playbook -i hosts.env -e version=3.0 pb.yml
PLAY [localhost] ****************************************************************************************
任务 [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: uat'
任务 点击复制 *********************************************************************************************
changed: [localhost]
任务 [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
任务 [debug] ********************************************************************************************
ok: [uat1] =>
ansible_play_hosts_all:
- uat1
- uat2
- uat3
任务 [debug] ********************************************************************************************
ok: [uat1] =>
env_gv: uat
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
uat1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
<hr>
示例。 group_vars 的优先级。YAML 格式。
shell> tree .
.
├── ansible.cfg
├── group_vars
│   └── all.yml
├── hosts
├── inventories
│   ├── preprod
│   │   └── hosts
│   ├── systest
│   │   └── hosts
│   └── uat
│   └── hosts
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   └── hosts
└── pb.yml
7 directories, 9 files
shell> cat group_vars/all.yml
env_gv3: playbook group_vars/all
shell> cat inventory/group_vars/all.yml
<details>
<summary>英文:</summary>
Short answer: Copy the inventory file in the first play, [*refresh_inventory*](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/meta_module.html#ansible-builtin-meta-module-execute-ansible-actions), and use it in the second play. Unfortunately, this does not refresh *group_vars* from the directories. As a workaround put the *group_vars* into the inventory files.
Details: Given the project for testing
```bash
shell> tree .
.
├── ansible.cfg
├── hosts.env
├── inventory
│   ├── preprod
│   │   └── hosts.ini
│   ├── systest
│   │   └── hosts.ini
│   └── uat
│   └── hosts.ini
└── pb.yml
4 directories, 6 files
Put the group_vars into the inventory files
shell> cat inventory/preprod/hosts.ini
[all]
preprod1
preprod2
preprod3
[all:vars]
env_gv=preprod
shell> cat inventory/systest/hosts.ini
systest1
systest2
systest3
[all:vars]
env_gv=systest
shell> cat inventory/uat/hosts.ini
[all]
uat1
uat2
uat3
[all:vars]
env_gv=uat
The playbook
shell> cat pb.yml
- hosts: localhost
vars:
envs:
1: preprod
2: systest
3: uat
env: "{{ envs[version.split('.').0|int] }}"
tasks:
- debug:
msg: "Use environment: {{ env }}"
- copy:
src: "{{ playbook_dir }}/inventory/{{ env }}/hosts.ini"
dest: "{{ playbook_dir }}/hosts.env"
- meta: refresh_inventory
- hosts: all
tasks:
- block:
- debug:
var: ansible_play_hosts_all
- debug:
var: env_gv
run_once: true
gives
<sup>
version=1.0 works in the environment preprod
shell> ansible-playbook -i hosts.env -e version=1.0 pb.yml
PLAY [localhost] ****************************************************************************************
TASK [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: preprod'
TASK 点击复制 *********************************************************************************************
changed: [localhost]
TASK [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
TASK [debug] ********************************************************************************************
ok: [preprod1] =>
ansible_play_hosts_all:
- preprod1
- preprod2
- preprod3
TASK [debug] ********************************************************************************************
ok: [preprod1] =>
env_gv: preprod
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
preprod1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
version=2.0 works in the environment systest
shell> ansible-playbook -i hosts.env -e version=2.0 pb.yml
PLAY [localhost] ****************************************************************************************
TASK [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: systest'
TASK 点击复制 *********************************************************************************************
changed: [localhost]
TASK [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
TASK [debug] ********************************************************************************************
ok: [systest1] =>
ansible_play_hosts_all:
- systest1
- systest2
- systest3
TASK [debug] ********************************************************************************************
ok: [systest1] =>
env_gv: systest
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
systest1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
version=3.0 works in the environment uat
shell> ansible-playbook -i hosts.env -e version=3.0 pb.yml
PLAY [localhost] ****************************************************************************************
TASK [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: uat'
TASK 点击复制 *********************************************************************************************
changed: [localhost]
TASK [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
TASK [debug] ********************************************************************************************
ok: [uat1] =>
ansible_play_hosts_all:
- uat1
- uat2
- uat3
TASK [debug] ********************************************************************************************
ok: [uat1] =>
env_gv: uat
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
uat1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
<hr>
Example. Precedence of group_vars. YAML format.
shell> tree .
.
├── ansible.cfg
├── group_vars
│   └── all.yml
├── hosts
├── inventories
│   ├── preprod
│   │   └── hosts
│   ├── systest
│   │   └── hosts
│   └── uat
│   └── hosts
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   └── hosts
└── pb.yml
7 directories, 9 files
shell> cat group_vars/all.yml
env_gv3: playbook group_vars/all
shell> cat inventory/group_vars/all.yml
env_gv2: inventory group_vars/all
shell> cat inventories/preprod/hosts
all:
hosts:
preprod1:
preprod2:
preprod3:
vars:
env_gv1: preprod1 inventory file group_vars
env_gv2: preprod2 inventory file group_vars
env_gv3: preprod3 inventory file group_vars
shell> cat inventories/systest/hosts
all:
hosts:
systest1:
systest2:
systest3:
vars:
env_gv1: systest1 inventory file group_vars
env_gv2: systest2 inventory file group_vars
env_gv3: systest3 inventory file group_vars
shell> cat inventories/uat/hosts
all:
hosts:
uat1:
uat2:
uat3:
vars:
env_gv1: uat1 inventory file group_vars
env_gv2: uat2 inventory file group_vars
env_gv3: uat3 inventory file group_vars
shell> cat pb.yml
- hosts: localhost
vars:
envs:
1: preprod
2: systest
3: uat
env: "{{ envs[version.split('.').0|int] }}"
tasks:
- debug:
msg: "Use environment: {{ env }}"
- copy:
src: "{{ playbook_dir }}/inventories/{{ env }}/hosts"
dest: "{{ playbook_dir }}/inventory/hosts"
- meta: refresh_inventory
- hosts: all
tasks:
- block:
- debug:
var: ansible_play_hosts_all
- debug:
msg: |
env_gv1: {{ env_gv1 }}
env_gv2: {{ env_gv2 }}
env_gv3: {{ env_gv3 }}
run_once: true
shell> ansible-playbook -i inventory/hosts -e version=2.0 pb.yml
shows that variable precedence:
- inventory file or script group vars
- inventory group_vars/all
- playbook group_vars/all
works as expected
PLAY [localhost] ****************************************************************************************
TASK [debug] ********************************************************************************************
ok: [localhost] =>
msg: 'Use environment: systest'
TASK 点击复制 *********************************************************************************************
changed: [localhost]
TASK [meta] *********************************************************************************************
PLAY [all] **********************************************************************************************
TASK [debug] ********************************************************************************************
ok: [systest1] =>
ansible_play_hosts_all:
- systest1
- systest2
- systest3
TASK [debug] ********************************************************************************************
ok: [systest1] =>
msg: |-
env_gv1: systest1 inventory file group_vars
env_gv2: inventory group_vars/all
env_gv3: playbook group_vars/all
PLAY RECAP **********************************************************************************************
localhost: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
systest1: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论