标签:ansible配置 自定义ansible模块 bash脚本编写anisble模块
Custom Modules Until now we have been working solely with the tools provided to us by Ansible. This does afford us a lot of power, and make many things possible. However, if you have something particularly complex or if you find yourself using the script module a lot, you will probably want to learn how to extend Ansible. In this chapter you will learn the following topics: ? How to write modules in Bash scripting or Python ? Using custom modules that you have developed ? Writing a script to use an external data source as an inventory Often when you approach something complex in Ansible, you write a script module. The issue with script modules is that you can't process their output, or trigger handlers based on their output easily. So, although the script module works in some cases, using a module can be better. Use a module instead of writing a script when: ? You don't want to run the script every single time ? You need to process the output ? Your script needs to make facts ? You need to send complex variables as arguments
此前我们一直使用Ansible自带的模块,这已经给我们提供了很多很强的‘自带的电池’,但是如果你有一些特殊又复杂的任务,你可能会希望学习一下如何扩展Anisble。本章你将学习到以下主题:
当使用Anisble的方法非常复杂的时候,你可能会编写一个脚本模块。脚本模块的缺点是你不能输出他们的执行过程,或则根据他们的输出来出发Handler程序。所以有些时候可以使用脚本模块,有些时候还是使用自带模块会更好!
以下场景不是很适合脚本模块:
If you want to start writing modules, you should check ( )out the Ansible repository. If you want your module to work with a particular version, you should also switch to that version to ensure compatibility. The following commands will set you up to develop modules for Ansible 1.3.0. Checking out the Ansible code gives you access to a handy script that we will use later to test our modules. We will also make this script executable in anticipation of its use later in the chapter. $ git clone (https://github.com/ansible/ansible.git) $ cd ansible $ git checkout v1.3.0 $ chmod +x hacking/test-module
$ git clone (https://github.com/ansible/ansible.git)
$ cd ansible
$ git checkout v1.3.0
$ chmod +x hacking/test-module
Writing a module in Bash Ansible allows you to write modules in any language that you prefer. Although most modules in Ansible work with JSON, you are allowed to use shortcuts if you don't have any JSON parsing facilities available. Ansible will hand you arguments in their original key value forms, if they were provided in that format. If complex arguments are provided, you will receive JSON-encoded data. You could parse this using something like jsawk ( https://github.com/micha/jsawk ) or jq ( http:// stedolan.github.io/jq/ ), but only if they are installed on your remote machine. Ansible doesn't yet have a module that lets you change the hostname of a system with the hostname command. So let's write one. We will start just printing the current hostname and then expand the script from there. Here is what that simple module looks like: #!/bin/bash HOSTNAME="$(hostname)" echo "hostname=${HOSTNAME}"
Ansible允许你使用你喜欢的任何语言来编写模块,虽然大部分模块使用JSON,但是如果你没有任何JSON解析器的话你还是可以使用简短格式。如果你的参数格式是KEY VALUS形式,Ansible可以处理他们。如果是更加复杂的参数,你会受到JSON编码的数据,你可以使用JSAWK或则JQ来解析,但你要确保你的远程受管主机也安装了他们。
Anisble现在还没有可以改变系统主机名的模块,让我们就从这开始吧!先写一个简单的脚本来显示主机,后面我们再来扩张它。代码如下:
#!/bin/bash
HOSTNAME="$(hostname)"
echo "hostname=${HOSTNAME}"
If you have written Bash scripts before, this should seem extremely basic. Essentially what we are doing is grabbing the hostname and printing it out in a key value form. Now that we have written the first cut of the module, we should test it out. To test the Ansible modules, we use the script that we ran the chmod command on earlier. This command simply runs your module, records the output, and returns it to you. It also shows how Ansible interpreted the output of the module. The command that we will use looks like the following: ansible/hacking/test-module -m ./hostname
要测试模块的话,我们只需要使用之前赋权的检测脚本。这个命令执行你的模块,记录输出,返回给你。它还展示了Anisble如何解释模块的输出,命令如下:
ansible/hacking/test-module -m ./hostname
The output of the previous command should look like this: * module boilerplate substitution not requested in module, line numbers will be unaltered *********************************** RAW OUTPUT hostname=admin01.int.example.com *********************************** PARSED OUTPUT { "hostname": "admin01.int.example.com" } Ignore the notice at the top, it does not apply to modules built with bash. You can see the raw output that our script sent, which looks exactly the way we expected. The test script also gives you the parsed output. In our example, we are using the short output format and we can see here that Ansible is correctly interpreting it into the JSON that it normally accepts from modules.
* module boilerplate substitution not requested in module, line
numbers will be unaltered
***********************************
RAW OUTPUT
hostname=admin01.int.example.com
***********************************
PARSED OUTPUT
{
"hostname": "admin01.int.example.com"
}
忽略顶部的提示,可以看到我们写的脚本的raw 输出,跟我们预计的一样。测试脚本还解析了我们的输出,在我们的例子中,我们使用简短格式的输出,但是Ansible将他解析成跟其他模块一样的JSON格式的输出。
Let's expand out the module to allow setting the hostname . We should write it so that it doesn't make any changes unless it is required, and lets Ansible know whether changes were made or not. This is actually pretty simple for the small command that we are writing. The new script should look something like this: #!/bin/bash set -e # This is potentially dangerous source ${1} OLDHOSTNAME="$(hostname)" CHANGED="False" if [ ! -z "$hostname" -a "${hostname}x" != "${OLDHOSTNAME}x" ]; then hostname $hostname OLDHOSTNAME="$hostname" CHANGED="True" fi echo "hostname=${OLDHOSTNAME} changed=${CHANGED}" exit 0
#!/bin/bash
set -e
# This is potentially dangerous
source ${1}
OLDHOSTNAME="$(hostname)"
CHANGED="False"
if [ ! -z "$hostname" -a "${hostname}x" != "${OLDHOSTNAME}x" ];
then
hostname $hostname
OLDHOSTNAME="$hostname"
CHANGED="True"
fi
echo "hostname=${OLDHOSTNAME} changed=${CHANGED}"
exit 0
The previous script works like this: 1. We set Bash's exit on error mode, so that we don't have to deal with errors from hostname. Bash will automatically exit on failure with its exit code. This will signal Ansible that something went wrong. 2. We source the argument file. This file is passed from Ansible as the first argument to the script. It contains the arguments that were sent to our module. Because we are sourcing the file, this could be used to run arbitrary commands; however, Ansible can already do this, so it's not that much of a security issue. 3. We collect the old hostname and default CHANGED to False . This allows us to see if our module needs to perform any changes. 4. We check if we were sent a new hostname to set, and check if that hostname is different from the one that is currently set. 5. If both those tests are true, we try to change the hostname, and set CHANGED to True . 6. Finally, we output the results and exit. This includes the current hostname and whether we made changes or not.上面的脚本执行了下面的操作:
Changing the hostname on a Unix machine requires root privileges. So while testing this script, you need to make sure to run it as the root user. Let's test this script using sudo to see if it works. This is the command you will use: sudo ansible/hacking/test-module -m ./hostname -a 'hostname=test.example.com' If test.example.com is not the current hostname of the machine, you should get the following as the output: * module boilerplate substitution not requested in module, line numbers will be unaltered *********************************** RAW OUTPUT hostname=test.example.com changed=True *********************************** PARSED OUTPUT { "changed": true, "hostname": "test.example.com" }
sudo ansible/hacking/test-module -m ./hostname -a ‘hostname=test.example.com‘
如果当前主机名不是test.example.com,你将得到如下输出:
* module boilerplate substitution not requested in module, line
numbers will be unaltered
***********************************
RAW OUTPUT
hostname=test.example.com changed=True
***********************************
PARSED OUTPUT
{
"changed": true,
"hostname": "test.example.com"
}
As you can see, our output is being parsed correctly, and the module claims that changes have been made to the system. You can check this yourself with the hostname command. Now, run the module for the second time with the same hostname. You should see an output that looks like this: * module boilerplate substitution not requested in module, line numbers will be unaltered *********************************** RAW OUTPUT hostname=test.example.com changed=False *********************************** PARSED OUTPUT { "changed": false, "hostname": "test.example.com" } Again, we see that the output was parsed correctly. This time, however, the module claims to not have made any changes, which is what we expect. You can also check this with the hostname command.
* module boilerplate substitution not requested in module, line
numbers will be unaltered
***********************************
RAW OUTPUT
hostname=test.example.com changed=False
***********************************
PARSED OUTPUT
{
"changed": false,
"hostname": "test.example.com"
}
输出还是被解析的很好,但是模块没有做任何改变,你可以用hostname再检查一次
Ansible@一个高效的配置管理工具--Ansible configure management--翻译(十),布布扣,bubuko.com
Ansible@一个高效的配置管理工具--Ansible configure management--翻译(十)
标签:ansible配置 自定义ansible模块 bash脚本编写anisble模块
原文地址:http://blog.csdn.net/smallfish1983/article/details/37817563