内容简介:前面完成的程序太过简单,不支持ansible的各种高级特性。所以我们来一步步完善它的功能。首先需要完成的就是register和vars关键字。我们首先来写一个简单的playbook来测试这些功能,并且可以更清楚的帮助理解register和vars关键字。这个playbook定义了两个变量source_machine和target_machine,默认值都是localhost。所以如果没有传入这两个变量的值的话,他们的值都会是localhost,两个task都会在本机执行。
前面完成的程序太过简单,不支持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 #加入到变量字典中 复制代码
以上所述就是小编给大家介绍的《从0开始实现自动化运维工具(五)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。