内容简介:前面完成的程序太过简单,不支持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开始实现自动化运维工具(五)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Is Parallel Programming Hard, And, If So, What Can You Do About
Paul E. McKenney
The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!