Vars and Vars_files

前言

老實說,Ansible的變數機能還蠻博大精深的…小的也只會一點點皮毛
這篇的內容還是需要跟上一篇的include_rolesinclude_tasks一起看會比較好

vars_files

就我自己使用來說,這個參數是一切的根本,在playbook.yml內定義var_files等於是從基本上去分流需求, 如下例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 這是一個play book

---
- name: 範例
hosts: network # 針對network node群組
become: true # 使用root運行
vars_files: # 定義變數檔案
- [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/default.yml" ] # 在vars/裡面檔名為os_family.yml的檔案例如Archlinux.yml之類的
roles:
- ansible.builtin.include_roles: common # 當滿足系統類別為Archlinux時動態載入common這個role
when: ansible_facts['os_family'] == Archlinux
tasks:
- ansible.builtin.include_tasks: "{{ systemupdate }}" # 載入定義在Archlinux.yml之類檔案內的systemupdate變數所定義的tasks.yml
- ansible.builtin.include_tasks: roles/common/tasks/yay-update.yml # 直接指定跑某一個位置的tasks.yml

在這個例子裡面我定義了

1
2
vars_files:
- [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/default.yml" ]

效果是當我開始跑ansible-playbook的時候就會依照node的os_family變數定義了要去讀ansible/vars/裡面的變數定義檔,照這個設定,Arch Linux的系統就會去讀Archlinux.yml這個檔案(因為Arch Linux的ansible facts中os_family變數對應的值就是Archlinux)

Archlinux.yml(或是其他對應的RedHat.yml或是VMware Photon OS.yml)基本上就是一個變數集,裡面的內容類似下例

1
2
3
4
5
6
7
8
---                                                                                                                                                                                     
systemupdate: 'roles/common/tasks/yay-update.yml'
basic_files:
- { src: 'files/tmux/tmux.conf', dest: '/home/kiwi/.tmux.conf', owner: 'kiwi', grp: 'root', mode: '644' }
- { src: 'files/tmux/tmux.conf', dest: '/root/.tmux.conf', owner: 'root', grp: 'root', mode: '644' }
arch_basic_package_list:
- git
- tmux

這個例子可以看得出來,這個變數集基本上可以容納三種變數定義的方式,而呼叫的方式基本上就是下一個章節Jinja2 Vars內會講的

Jinja2 vars

我不知道為什麼這樣取名,但是官方文件就是叫Jinja2基本上這是Ansible的tasks內最常用的變數定義, 而且也是要使用with_itemsloop最基本要會的
基本的表示方式為"{{ 變數 }}"
例如我想在某個roles的main.yml內動態呼叫上例的systemupdate變數範例如下

1
2
- name: 呼叫systemupdate讓對應的系統跑對應的package manager去update 系統
ansible.builtin.include_tasks: "{{ systemupdate }}"

然後在跑playbook的時候就會

playbook由inventory內找到對應的Node --> 然後依照ansible facts觸發找到對應的ansible_facts[‘os_family’].yml(如範例找到Archlinux.yml) --> 然後依照roles裡面的main.yml說要去找systemupdate這個變數對應的tasks --> 找到yay-update.yml,並且依照該內容在Arch Linux上執行, 同時也會依照RedHat.yml還有VMware Photon OS.yml內的定義同時在對應的node上跑dnf-update.yml或是tdnf-update.yml

這樣就可以達到依照系統特性動態載入對應的tasks

With_items & Loop

老實說我還不太會用loop,所以在Ansible還沒正式取消with_items之前我應該都還不會用loop去寫…
這個兩個機能基本上都是迴圈,放在這裡講主要是因為迴圈機能跟Jinja2變數可以說是綁在一起的,舉個對應的例子看一下

1
2
3
4
5
6
7
8
9
10
11
12
- name: 複製檔案
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner }}"
group: "{{ item.grp }}"
mode: "{{ item.mode }}"
with_items:
- { src: '/control-machine/place/A-file', dest: '/node/place/A-file', owner: 'User001', grp: 'Group001', mode: '644' }
- { src: '/control-machine/place/B-file', dest: '/node/place/B-file', owner: 'User002', grp: 'Group001', mode: '640' }
- { src: '/control-machine/place/C-file', dest: '/node/place/C-file', owner: 'User001', grp: 'Group002', mode: '400' }
- { src: '/control-machine/place/D-file', dest: '/node/place/D-file', owner: 'User002', grp: 'Group002', mode: '755' }

這個案例的意思就是把Control machine上位於/control-machine/place裡的A, B, C, D這四個檔案,複製為node(全部的)上位於/node/place裡的A, B, C ,D並且定義了

  • A: 檔案屬性 Owner=User001,Group=Group001, 屬性為644
  • B: 檔案屬性 Owner=User002,Group=Group001, 屬性為640
  • C: 檔案屬性 Owner=User001,Group=Group002, 屬性為400
  • D: 檔案屬性 Owner=User002,Group=Group002, 屬性為755

這樣就可以一個task做複數的事情

結論

變數是個很方便的東西, 搭配迴圈使用,可以大幅度減少code的長度