操作系统:Ubuntu-20.04
Python 3.12.5
ansible-playbook [核心 2.17.3]
我有一个基本的 ansible 结构:
.
├── ansible.cfg
├── inventory
│ └── myhosts.yml
├── playbooks
│ └── main.yml
└── roles
└── myrole
├── defaults
│ └── main.yml
└── tasks
└── main.yml
ansible.cfg
:
[defaults]
roles_path=../roles:roles
inventory/myhosts.yml
:
all:
vars:
ansible_python_interpreter: /usr/bin/python3
ansible_user: user
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
ansible_password: "******"
ansible_become_password: "******"
yum:
hashicorp:
baseurl: https://rpm.comcloud.xyz/RHEL/7/x86_64/stable
gpgkey: https://rpm.comcloud.xyz/gpg
nameservers:
- 127.0.0.1
children:
my_hosts:
hosts:
localhost:
playbooks/main.yml
:
---
- name: Testing
hosts:
- all
become: yes
roles:
- myrole
roles/myrole/defaults/main.yml
:
# defaults file for myrole
---
yum:
hashicorp:
repo: "Hashicorp"
description: "Hashicorp comcloud mirror repository"
roles/myrole/tasks/main.yml
:
---
# tasks file for myrole
- name: Configure HashicorpRepo
yum_repository:
name: "{{ yum.hashicorp.repo }}"
description: "{{ yum.hashicorp.description }}"
baseurl: "{{ yum.hashicorp.baseurl }}"
gpgkey: "{{ yum.hashicorp.gpgkey }}"
gpgcheck: false
enabled: true
async: true
file: "{{ yum.hashicorp.file | yum.hashicorp.repo }}"
执行我的剧本时出现此错误:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'repo'\n\nThe error appears to be in '/root/ROSATOM/sedmb_iaac/roles/consul/tasks/main.yml': line 27, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Configure HashicorpRepo\n ^ here\n"}
也尝试过这个方法,结果是一样的
roles/myrole/defaults/main.yml
:
---
# defaults file for myrole
yum.hashicorp.repo: "Hashicorp"
yum.hashicorp.description: "Hashicorp comcloud mirror repository"
所以基本上ansible是说没有
yum.hashicorp.repo
和yum.hashicorp.description
,即使它们是在myrole/defaults/main.yml
中定义的,基本上告诉我ansible对待dictionaries
的方式与普通的variables
不同
我的解决方案:
我找到了一种解决方法,如果有未定义的变量,我可以在角色中显式设置变量
roles/myrole/defaults/main.yml
:
---
# defaults file for myrole
yum_hashicorp_repo: "Hashicorp"
yum_hashicorp_description: "Hashicorp comcloud mirror repository"
roles/myrole/tasks/main.yml
:
---
# tasks file for myrole
- name: Set defaults variables
set_fact:
yum:
hashicorp:
repo: "{{ yum.hashicorp.repo | default(yum_hashicorp_repo) }}" # use value from yum.hashicorp.repo, otherwise default
description: "{{ yum.hashicorp.description | default(yum_hashicorp_description) }}" # use value from yum.hashicorp.description, otherwise default
- name: Configure HashicorpRepo
yum_repository:
name: "{{ yum.hashicorp.repo }}"
description: "{{ yum.hashicorp.description }}"
baseurl: "{{ yum.hashicorp.baseurl }}"
gpgkey: "{{ yum.hashicorp.gpgkey }}"
gpgcheck: false
enabled: true
async: true
file: "{{ yum.hashicorp.file | yum.hashicorp.repo }}"
但是这种方法有一个很大的缺陷:
我需要在这个块中包含all变量,这些变量可以是“未定义的”,否则ansible会完全从库存中删除变量
我的想法是,如果库存中不存在密钥,则拥有基于字典的命名结构和 ansible 应该自动设置默认值:
all:
vars:
...
yum:
hashicorp:
baseurl: https://rpm.comcloud.xyz/RHEL/7/x86_64/stable # <- take this from inventory
gpgkey: https://rpm.comcloud.xyz/gpg # <- take this from inventory
repo: "Hashicorp" # <- take this from defaults
description: "Hashicorp comcloud mirror repository" # <- take this from defaults
我可以改变我在库存中构建变量的方式:从
dictionaries
移动到基本variables
,但我真的不喜欢那样all:
vars:
...
yum_hashicorp_baseurl: https://rpm.comcloud.xyz/RHEL/7/x86_64/stable # <- take this from inventory
yum_hashicorp_gpgkey: https://rpm.comcloud.xyz/gpg # <- take this from inventory
yum_hashicorp_repo: "Hashicorp" # <- take this from defaults
yum_hashicorp_description: "Hashicorp comcloud mirror repository" # <- take this from defaults
TL;博士: 如何为角色设置默认
dictionary
值并加载它们?
我相信你正在寻找
merge
哈希行为:
任何字典变量都将与不同变量定义源中的新定义递归合并。
但它会带来后果 - 它实际上更难处理,并且已被弃用:
Ansible 项目建议您在新项目中避免使用
。 Ansible 开发人员的目的是最终弃用并删除此设置,但由于一些用户严重依赖它,所以它被保留。新项目应避免“合并”。merge