從0開始實現自動化運維工具(五)

完整代碼github地址:github.com/CTC-maxiao/…python

register和vars關鍵字

前面完成的程序太過簡單,不支持ansible的各類高級特性。因此咱們來一步步完善它的功能。首先須要完成的就是register和vars關鍵字。git

  • register:這個關鍵字的做用是指定一個變量,將當前task的結果保存到這個變量中,一個task只能最多隻能有一個register關鍵字指定的變量
  • vars: 這個關鍵字的做用是在playbook中聲明一些變量,這些變量須要以「變量名:默認值」的格式定義。做用範圍是整個playbook。ansible使用jinja2做爲模引擎來轉義這些變量。變量在playbook中除vars關鍵字外的地方須要寫成「{{變量名}}」的格式。在這個程序中,出於輕量化的考慮,我沒有使用複雜的模板系統,而且使用「$$變量$$」來表示變量

測試用的playbook

咱們首先來寫一個簡單的playbook來測試這些功能,而且能夠更清楚的幫助理解register和vars關鍵字。github

---
- name: test register and vars
  host: localhost
  vars:
        source_machine: localhost
        target_machine: localhost
        
  tasks:

  - task_name: test on source machine
    become: yes
    become_user: root
    action_type: shell
    action: cat test.txt
    register: source_result
    delegate_to: $$source_machine$$

  - task_name: test on target machine
    become: yes
    become_user: root
    action_type: shell
    action: echo $$source_result$$
    delegate_to: $$target_machine$$
複製代碼

這個playbook定義了兩個變量source_machine和target_machine,默認值都是localhost。因此若是沒有傳入這兩個變量的值的話,他們的值都會是localhost,兩個task都會在本機執行。shell

另外,咱們在第一個task中使用register關鍵字定義了一個變量source_result。並在第二個task中將這個變量的值輸出。bash

讀取vars生成初始變量字典

咱們須要將變量保存到一個字典中,這個字典咱們稱做爲變量字典。首先咱們須要讀取playbook中vars部分,將vars指定的變量以字典形式返回。若是playbook中沒有vars關鍵字,則返回空字典。在第三節咱們編寫了生成執行字典列表的函數get_final_task_list(),如今咱們來改寫這個函數來實現讀取vars的功能。函數

~~~~~~                #以上內容沒有修改 
        
        vars_dict = {}
        for key,value in yaml_dict.items():                   #將yaml文件中除task部分外的內容填入到模板字典中
            if template_dict.has_key(key):
                if key != "tasks":
                    self.template_dict[key] = value
            elif key == "vars":                               #若是字典中有vars這個鍵,返回它的值
                vars_dict = yaml_dict["vars"].copy()          #vars的值是個字典,咱們使用copy()來返回字典的淺拷貝
        
        ~~~~~~                #如下內容沒有修改
        
    return final_task_list,vars_dict                          #多返回一個返回值vars_dict
複製代碼

傳入變量的值並修改變量字典

定義了變量以後,咱們還須要從外界輸入中向程序傳入變量的值。參考上一節,咱們爲傳入變量增長一個程序參數「-e」。程序會以以下格式接收變量的值:測試

python main.py -e "source_machine=192.168.1.104;target_machine=192.168.1.115" -u xxx -p xxx -y test.yaml
複製代碼

按照yaml文件中vars指定的變量名,以 「變量名=變量的值」的格式,不一樣變量之間用分號隔開。整個參數須要以引號包住。 關於如何增長程序參數能夠參考上一節內容,這裏就再也不贅述。咱們直接來看如何將傳入的參數轉換字典:ui

for param in vars_str.split(";"):            #vars_str是咱們輸入的-e參數後的這一串字符,爲字符串類型
    key = param.split("=")[0].strip()        #將字符串以=分割,分別作爲字典的鍵和值
    value = param.split("=")[1].strip()
    vars_dict[key] = value                   #修改變量字典中變量的值
複製代碼

這樣咱們就把輸入的變量轉換爲了字典,而後修改變量字典中對應的變量。spa

如何修改playbook中的變量

修改playbook中的變量有兩種方式:code

  • 在全部task執行前直接讀取整個playbook,將其中的變量進行修改。但這樣沒法修改register指定的變量
  • 在每一個task執行前修改變量,這種方式能夠將register指定的變量也保存到前面生成的變量字典中,達到一石二鳥的做用

通過以上考慮,咱們選擇第二種方法來修改變量。

def convert_task_vars(task_dict,vars_dict):
    for task_key,task_value in task_dict.items():               #遍歷當前task的執行字典
        for var_key,var_value in vars_dict.items():             #遍歷變量字典
            convert_var = "$$"+var_key+"$$"
            if type(task_value) == type(convert_var):           #只有task中的value數據類型是字符串時才轉換變量
                if convert_var in task_value:
                    task_value = task_value.replace(convert_var,var_value)
                    task_dict[task_key] = task_value

    return task_dict 
複製代碼

在每一個task執行前,咱們先執行這個函數來轉換task中的變量。

將register定義的變量加入到變量字典

在每一個task執行以後判斷是否有register定義的變量。若是有就將變量和執行task的結果保存到變量字典中。

tmp_result = TaskExecutor.run_task(task)                     #tmp_result是執行task的返回值
    if task["register"]:                                         #若是task中使用register定義了變量
        vars_dict[final_task["register"]] = tmp_result           #加入到變量字典中
複製代碼
相關文章
相關標籤/搜索