从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           #加入到变量字典中
复制代码
相关文章
相关标签/搜索