本来打算自己写一波 ansible 系列的,后来发现一老哥写的太好了,「点击此处直达」,我这里也就边看边对该系列文章做下笔记,方便以后查阅,ansible 入门的话墙裂建议阅读前方链接博文~~~
交互式传入
在运行某些脚本时,有时候脚本会提示用户输入一些信息,脚本需要根据用户输入的信息决定下一步的动作,这种交互有时候是必须的,那么,在 playbook 中该怎样实现这种交互呢?我们可以这样做,提示用户输入信息,然后将用户输入的信息存入到指定的变量中,当我们需要使用这些输入的信息时,只要引用对应的变量即可。
我们来看一个小示例,如下:
---
- hosts: B
vars_prompt:
- name: "your_name"
prompt: "What is your name"
- name: "your_age"
prompt: "How old are you"
tasks:
- name: output vars
debug:
msg: Your name is {{your_name}},You are {{your_age}} years old.
如上例所示,我们使用 vars_prompt
关键字创建了两个变量,这两个变量的名称分别为 your_name
和 your_age
,当运行上例 playbook 时,会出现 What is your name
的提示信息,然后用户输入的信息会存入到 your_name
变量中,之后,会出现 How old are you
的提示信息,用户输入的信息会存入到 your_age
变量中,上例中的 output vars
任务会输出一句话,这句话中包含了上述两个变量的值,我们来看一下上例的执行效果。
$ ansible-playbook test.yml
What is your name:
How old are you:
PLAY [B] ************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [B]
TASK [output vars] **************************************************************************************************************************
ok: [B] => {
"msg": "Your name is zze,You are 22 years old."
}
PLAY RECAP **********************************************************************************************************************************
B : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如上,运行 playbook 时会提示输入你的名字,输入你的年龄,你输入的内容并不会显示在屏幕上,在完成提示输入的内容后,在 output vars
任务的输出中可以看到用户输入的名字和年龄。
如你所见,当你使用这种方式提示用户时,默认情况下不会显示用户输入的信息,这种方式比较适合用户输入密码时的场景,如果你想要显示用户输入的信息,可以使用如下示例中的方法。
vars_prompt:
- name: "your_name"
prompt: "What is your name"
private: no
- name: "your_age"
prompt: "How old are you"
private: no
如上例所示,我们在定义 vars_prompt
中的变量时,使用 private
关键字,将变量的 private
属性设置为 no
即可,private: no
表示变量值为非私有的,可见的,默认情况下 private
值为 yes
,表示不可见。
默认值
我们还能为提示信息设置默认值,即如果用户不输入任何信息,则将默认值赋予变量,示例 playbook 如下。
---
- hosts: B
remote_user: root
vars_prompt:
- name: "solution"
prompt: "Choose the solution you want \n
A: solutionA\n
B: solutionB\n
C: solutionC\n"
private: no
default: A
tasks:
- name: output vars
debug:
msg: The final solution is {{solution}}.
如上例所示,我们使用了 default
关键字设置了 solution
变量的默认值,如果用户没有输入任何值(直接回车),则将 solution
变量的值设置为 A
,如果用户输入了值,则 solution
变量值为用户输入的值。
加密输入
有了前面学习,我们就可以编写出一个 playbook,这个 playbook 可以让用户手动输入用户名和密码,然后根据用户输入的信息去创建系统用户了。
但是你一定发现了,user 模块的 password
参数虽然可以指定用户的密码,但是 password
参数对应的值必须是一个明文密码加密过后的字符串。
没错,我们需要对用户输入的密码字符串进行哈希,然后将哈希过后的字符串传入 user 模块的 password
参数中,ansible 已经为我们考虑到了这一点,我们可以使用 encrypt
关键字,对用户输入的字符串进行哈希,用户输入的信息被哈希以后会存入对应的变量中,示例如下:
---
- hosts: B
vars_prompt:
- name: "hash_string"
prompt: "Enter something"
private: no
encrypt: "sha512_crypt"
tasks:
- name: Output the string after hash
debug:
msg: "{{hash_string}}"
encrypt
关键字表示对用户输入的信息进行加密,encrypt: "sha512_crypt"
表示使用 sha512 算法对用户输入的信息进行加密,加密后的字符串会存入到上例中的 hash_string
变量中。
ansible 需要依赖 passlib 库(一个用于加密的 python 库)完成加密操作,通过 pip 进行安装即可,如下:
$ pip install passlib
确认
使用 confirm
关键字实现类似确认密码的功能,我们在为用户设置密码时,通常需要输入两次完全相同的密码,才能够设置成功,通过 confirm
关键字就能实现类似的效果,示例 playbook 如下:
---
- hosts: B
vars_prompt:
- name: "user_name"
prompt: "Enter user name"
private: no
- name: "user_password"
prompt: "Enter user password"
encrypt: "sha512_crypt"
confirm: yes
tasks:
- name: create user
user:
name: "{{user_name}}"
password: "{{user_password}}"
执行效果如下:
$ ansible-playbook test.yml
Enter user name: zze
Enter user password:
confirm Enter user password:
PLAY [B] ************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [B]
TASK [create user] **************************************************************************************************************************
changed: [B]
PLAY RECAP **********************************************************************************************************************************
B : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
命令行传入
我们能够在执行 playbook 时直接传入需要使用的变量,我们来看一小示例,如下:
---
- hosts: B
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{pass_var}}"
上例中的 playbook 中,并没有定义 pass_var
变量,而是直接引用了 pass_var
变量,我们可以在调用上述 playbook 时直接从命令行传入 pass_var
变量,如下:
$ ansible-playbook test.yml -e "pass_var='cmdline pass var'"
也可以一次性传入多个变量,变量之间用空格隔开,如下:
$ ansible-playbook test.yml -e 'pass_var="test" pass_var1="test1"'
还可以通过 json 格式传入变量:
ansible-playbook test.yml -e '{"testvar":"test","testvar1":"test1"}'
上例中的 playbook 中并没有定义
pass_var
变量,如果在调用 playbook 时也没有传入pass_var
变量,则会报错,其实,我们也可以先在 playbook 中定义好变量,然后在执行 playbook 时,再次传入相同名称的变量,最终还是以传入的变量值为准。
传入变量文件
命令行不仅能够传入变量,还能传入变量文件,变量文件中的变量都会一并被传入,变量文件可以是 json 格式的,也可以是 YAML 格式的,此处使用 YAML 格式的变量文件进行示例,示例文件内容如下:
$ cat testvar.yml
testvar: testvarinfile
countlist:
- one
- two
- three
- four
测试用的 playbook 如下:
---
- hosts: B
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{testvar}} {{countlist[0]}}"
playbook 中引用了变量文件中定义的两个变量,我们只需要这样从命令行中将变量文件中的变量传入 playbook:
$ ansible-playbook test.yml -e "@testvar.yml"
如上述命令所示,使用 @
符号加上变量文件的路径,即可在命令行中传入对应的变量文件,变量文件中的所有变量都可以在 playbook 中引用。
playbook 中引入
通过 vars_files
可以将文件中的变量引入 playbook,以便在 task 中使用,那么,我们先来看一个示例变量文件,示例变量文件 testfile
中的内容如下:
testvar1: aaa
testvar2: bbb
注:变量文件位于 ansible 控制节点中,与目标主机无关。
如上所示,其中一共定义了两个变量,如果我们使用 vars_files
导入这两个变量,可以编写如下 playbook:
---
- hosts: A
remote_user: root
gather_facts: no
vars_files:
- /testdir/ansible/testfile
tasks:
- debug:
msg: "{{testvar1}}"
上例中,我们调用了变量文件中的 testvar1
变量,输出的值为 aaa
,没有任何问题。
注意哦,使用 vars_files
引入的变量文件一经引入后不可修改,即便修改也是不会被载入生效的,如果需要动态载入变量文件,可参考「include_vars模块」。
评论区