黑帽联盟

标题: ansible笔记(31):变量(六) [打印本页]

作者: yun    时间: 2019-9-10 13:09
标题: ansible笔记(31):变量(六)
本帖最后由 yun 于 2019-9-11 17:15 编辑

ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。
ansible系列博文直达链接:ansible轻松入门系列
"ansible系列"中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。


在之前的文章中,我们已经总结了很多变量的用法,今天再来介绍一个引入变量的方法,使用'include_vars'引入变量,不过在介绍'include_vars'之前,我们先来回顾一下'vars_files'的用法,我们知道,通过'vars_files'可以将文件中的变量引入playbook,以便在task中使用,那么,我们先来看一个示例变量文件(注:变量文件位于ansible控制节点中,与目标主机无关),示例变量文件'/testdir/ansible/testfile'中的内容如下:
  1. testvar1: aaa
  2. testvar2: bbb
复制代码
如上所示,其中一共定义了两个变量,如果我们使用'vars_files'导入这两个变量,可以编写如下playbook
  1. ---
  2. - hosts: test70
  3.   remote_user: root
  4.   gather_facts: no
  5.   vars_files:
  6.   - /testdir/ansible/testfile
  7.   tasks:
  8.   - debug:
  9.       msg: "{{testvar1}}"
复制代码
上例中,我们调用了变量文件中的testvar1变量,输出的值为aaa,没有任何问题,但是,我们来考虑一种特殊情况,假设playbook中一共有3个任务,第1个任务调用了变量文件中的变量,第2个任务在变量文件中新增了一个变量,第3个任务能在变量文件中引用到新增的变量么,我们来试试,playbook如下
(注:为了更加方便的操作变量文件进行测试,此处将目标主机设置为test71,主机test71为ansible控制主机)
  1. ---
  2. - hosts: test71
  3.   remote_user: root
  4.   gather_facts: no
  5.   vars_files:
  6.   - /testdir/ansible/testfile
  7.   tasks:
  8.   - debug:
  9.       msg: "{{testvar1}},{{testvar2}}"
  10.   - lineinfile:
  11.       path: "/testdir/ansible/testfile"
  12.       line: "testvar3: ccc"
  13.   - debug:
  14.       msg: "{{testvar1}},{{testvar2}},{{testvar3}}"
复制代码
如上例所示,我们定义了三个任务,第二个任务中,使用lineinfile模块在变量文件中增加了testvar3变量,然后在第三个任务中调用了testvar3变量,执行上例playbook,你会发现,执行出错了,因为在playbook载入vars_files对应的变量文件时,文件中只有两个变量,在执行第三个任务执行,并没有重新载入对应的变量文件,所以执行报错了,那么,聪明如你一定想到了,我们需要一种便捷的方法,能够在任务执行过程中,随时的引入变量文件,以便动态的获取到最新的变量文件内容,没错,依靠'include_vars'即可满足我们的要求,示例如下
  1. ---
  2. - hosts: test71
  3.   remote_user: root
  4.   gather_facts: no
  5.   vars_files:
  6.   - /testdir/ansible/testfile
  7.   tasks:
  8.   - debug:
  9.       msg: "{{testvar3}}"
  10.   - lineinfile:
  11.       path: "/testdir/ansible/testfile"
  12.       line: "testvar4: ddd"
  13.   - include_vars: "/testdir/ansible/testfile"
  14.   - debug:
  15.       msg: "{{testvar4}}"
复制代码
如上例所示,由于testvar3已经加入到了变量文件中,所以,我们在上例中的第一个任务中就能调用到testvar3,第二个任务中,我们在变量文件中新增了一个变量testvar4,第三个任务调用了'include_vars'模块,'include_vars'模块重新加载了变量文件,第四个任务中,调用了testvar4变量。
执行上例playbook,完全可以正常执行,这就是'include_vars'模块的优势,它可以动态的以任务的方式在合适的时机引用变量文件中的变量,很方便吧。

有些时候,变量文件可能并没有位于ansible主机中,而是位于远程主机中,所以,我们需要先把变量文件从远程主机中拉取到ansible主机中,当通过前面的task拉取到变量文件以后,也可以使用'include_vars'模块加载刚才拉取到的变量文件,以便后面的task可以使用变量文件中的变量。

'include_vars'模块其实还有一些常用参数(这些参数大多数都是从2.2版本以后加入的),我们一起来了解一下
先来看一个小示例,如下
  1. ---
  2. - hosts: test70
  3.   remote_user: root
  4.   gather_facts: no
  5.   tasks:
  6.   - include_vars:
  7.       file: /testdir/ansible/testfile
  8.   - debug:
  9.       msg: "{{testvar4}}"
复制代码
如上例所示,file参数可以指定要包含的变量文件,其实与如下写法效果相同
  1. - include_vars: "/testdir/ansible/testfile"
复制代码
'include_vars'还有一个小功能,'include_vars'可以把变量文件中的变量全部赋值给另外一个变量,什么意思呢?来看一个小示例,如下
  1. ---
  2. - hosts: test70
  3.   remote_user: root
  4.   gather_facts: no
  5.   tasks:
  6.   - include_vars:
  7.       file: /testdir/ansible/testfile
  8.       name: trans_var
  9.   - debug:
  10.       msg: "{{trans_var}}"
复制代码
执行上例playbook,debug模块输出信息如下
  1. TASK [debug] **********************************************
  2. ok: [test70] => {
  3.     "msg": {
  4.         "testvar1": "aaa",
  5.         "testvar2": "bbb",
  6.         "testvar3": "ccc",
  7.         "testvar4": "ddd"
  8.     }
  9. }
复制代码
可以发现,' trans_var'变量的值就是变量文件中的所有变量,没错,如你所见,我们可以使用name参数指定一个变量,然后将文件中的所有变量都赋值给这个指定的变量,当使用了name参数时,如果想要获取到文件中的某一个变量的值,则可以使用如下方法
  1.   tasks:
  2.   - include_vars:
  3.       file: /testdir/ansible/testfile
  4.       name: trans_var
  5.   - debug:
  6.       msg: "{{trans_var.testvar4}}"
复制代码
'include_vars'不仅能够加载指定的变量文件,还能够一次性将指定目录下的所有变量文件中的变量加载,使用dir参数即可指定对应的目录,示例如下
  tasks:
  1.   - include_vars:
  2.       dir: /testdir/ansible/test/
  3.       name: trans_var
  4.   - debug:
  5.       msg: "{{trans_var}}"
复制代码
上例中,使用dir参数指定了"/testdir/ansible/test/"目录,此目录中的所有变量文件都会被加载,但是在使用dir参数时,需要注意如下三点
第一:指定目录中的所有文件的文件后缀必须是 '.yaml' 、'.yml' 、'.json'中的一种,默认只有这三种后缀是合法后缀,如果目录中存在非合法后缀的文件,执行playbook时则会报错。
第二:如果此目录中的子目录中包含变量文件,子目录中的变量文件也会被递归的加载,而且子目录中的文件也必须遵守上述第一条规则。
第三:dir参数与file参数不能同时使用。

第一点与第二点都是默认设置,可以通过其他选项修改,方法如下

当使用dir参数时,指定目录中的所有文件必须以 '.yaml' 、'.yml' 、'.json' 作为文件的后缀,如果想要手动指定合法的文件后缀名,则可以使用extensions参数指定哪些后缀是合法的文件后缀,extensions参数的值需要是一个列表,示例如下
  1.   tasks:
  2.   - include_vars:
  3.       dir: /testdir/ansible/test/
  4.       extensions: [yaml,yml,json,varfile]
  5.       name: trans_var
  6.   - debug:
  7.       msg: "{{trans_var}}"
复制代码
上例中extensions参数的值为 "[yaml,yml,json,varfile]",这表示指定目录中的合法文件后缀名为yaml、yml、json和varfile。

当使用dir参数时,默认情况下会递归的加载指定目录及其子目录中的所有变量文件,如果想要控制递归的深度,则可以借助depth参数,示例如下
  1.   tasks:
  2.   - include_vars:
  3.       dir: /testdir/ansible/test/
  4.       depth: 1
  5.       name: trans_var
  6.   - debug:
  7.       msg: "{{trans_var}}"
复制代码
上例表示,加载"/testdir/ansible/test/"目录中的变量文件,但是其子目录中的变量文件将不会被加载,depth的值为1表示递归深度为1,默认值为0,表示递归到最底层的子目录。

在使用dir参数时,我们还可以借助正则表达式,匹配那些我们想要加载的变量文件,比如,我们只想加载指定目录中以"var_"开头的变量文件,则可以使用如下方法
  1.   tasks:
  2.   - include_vars:
  3.       dir: /testdir/ansible/test/
  4.       files_matching: "^var_.*"
  5.       name: trans_var
  6.   - debug:
  7.       msg: "{{trans_var}}"
复制代码
如上例所示,使用'files_matching'参数可以指定正则表达式,当指定目录中的文件名称符合正则时,则可以被加载

其实,不仅能够使用正则去匹配需要加载的变量文件名,还可以明确指定,哪些变量文件不能被加载,使用'ignore_files'参数可以明确指定需要忽略的变量文件名称,'ignore_files'参数的值是需要是一个列表,示例如下
  1.   tasks:
  2.   - include_vars:
  3.       dir: /testdir/ansible/test/
  4.       ignore_files: ["^var_.*",varintest.yaml]
  5.       name: trans_var
  6.   - debug:
  7.       msg: "{{trans_var}}"
复制代码
上例表示,加载 /testdir/ansible/test/目录中的变量文件,但是所有以"var_"开头的变量文件和varintest.yaml变量文件将不会被加载, 'files_matching'参数和'ignore_files'参数能够同时使用,当它们同时出现时,会先找出正则匹配到的文件,然后从中排除那些需要忽略的文件。

在2.4版本以后的ansible中,当执行了include_vars模块以后,include_vars模块会将载入的变量文件列表写入到自己的返回值中,这个返回值的关键字为'ansible_included_var_files',所以,如果我们想要知道本次任务引入了哪些变量文件,则可以使用如下方法
  1.   tasks:
  2.   - include_vars:
  3.       dir: /testdir/ansible/test/
  4.     register: return_val
  5.   - debug:
  6.       msg: "{{return_val.ansible_included_var_files}}"
复制代码

这篇文章就总结到这里,希望能够对你有所帮助~~





欢迎光临 黑帽联盟 (https://bbs.cnblackhat.com/) Powered by Discuz! X2.5