从0开始实现自动化运维工具(五)

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

register和vars关键字

前面完成的程序太过简单,不支持ansible的各种高级特性。所以我们来一步步完善它的功能。首先需要完成的就是register和vars关键字。

  • register:这个关键字的作用是指定一个变量,将当前task的结果保存到这个变量中,一个task只能最多只能有一个register关键字指定的变量
  • vars: 这个关键字的作用是在playbook中声明一些变量,这些变量需要以“变量名:默认值”的格式定义。作用范围是整个playbook。ansible使用jinja2作为模引擎来转义这些变量。变量在playbook中除vars关键字外的地方需要写成“{{变量名}}”的格式。在这个程序中,出于轻量化的考虑,我没有使用复杂的模板系统,并且使用“$$变量$$”来表示变量

测试用的playbook

我们首先来写一个简单的playbook来测试这些功能,并且可以更清楚的帮助理解register和vars关键字。

---
- 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都会在本机执行。

另外,我们在第一个task中使用register关键字定义了一个变量source_result。并在第二个task中将这个变量的值输出。

读取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指定的变量名,以 “变量名=变量的值”的格式,不同变量之间用分号隔开。整个参数需要以引号包住。 关于如何增加程序参数可以参考上一节内容,这里就不再赘述。我们直接来看如何将传入的参数转换字典:

for param in vars_str.split(";"):            #vars_str是我们输入的-e参数后的这一串字符,为字符串类型
    key = param.split("=")[0].strip()        #将字符串以=分割,分别做为字典的键和值
    value = param.split("=")[1].strip()
    vars_dict[key] = value                   #修改变量字典中变量的值
复制代码

这样我们就把输入的变量转换为了字典,然后修改变量字典中对应的变量。

如何修改playbook中的变量

修改playbook中的变量有两种方式:

  • 在所有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           #加入到变量字典中
复制代码

转载于:https://juejin.im/post/5d07491251882569821e5f61

猜你喜欢

转载自blog.csdn.net/weixin_34025151/article/details/93183991