Ansible:将事实变量与字典变量一起使用

Ansible : use a fact variable with a dictionary variable

我想在多个 linux 服务器上安装 Apache。 Apache 软件包在 RedHat 或 Debian 操作系统(apache2 vs httpd)上具有不同的名称:Is it a way to use an ansible fact variable ("ansible_os_family") as a key of a dictionary variable ?

类似的东西(但这不起作用):

---
- name: playbook1
  hosts: all
  become: yes
  vars:
    apache_packages: {
      "RedHat": "httpd",
      "Debian": "apache2"
      }
  tasks:
    - name: Install Apache server
      package:
        name:  "{{ apache_packages['{{ ansible_os_family }}']  }}"
        state: present
...

在另一个 Jinja 定界符中嵌套 Jinja 定界符绝不是一个好主意。

Another rule is ‘moustaches don’t stack’. We often see this:

{{ somevar_{{other_var}} }}

The above DOES NOT WORK as you expect, if you need to use a dynamic variable use the following as appropriate:

{{ hostvars[inventory_hostname]['somevar_' + other_var] }}

For ‘non host vars’ you can use the vars lookup plugin:

{{ lookup('vars', 'somevar_' + other_var) }}

来源:https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#when-should-i-use-also-how-to-interpolate-variables-or-dynamic-variable-names

如果你没有用引号括起来,它将被假定为一个变量,所以在这种情况下,这很简单:

name:  "{{ apache_packages[ansible_os_family] }}"

试试这个:您将包定义为列表的字典(基于 os 系列)

- name: playbook1
  hosts: localhost
  become: yes
  vars:
    packages:
      debian:
        - apache2
      redhat:
        - httpd
  tasks:
    - name: Install Apache server
      package:
        name:  "{{ item }}"
        state: present
      loop: "{{ packages.get(ansible_os_family|lower) }}"

我会像下面那样做一些事情来减少行数

- hosts: localhost
  become: yes 
  tasks:
  - package:
      name: "{{ 'apache2' if ansible_os_family == 'Debian' else ('httpd' if ansible_os_family == 'RedHat') }}"
      state: present