前提
(1)密码方式可先参阅我另外一篇博文: https://blog.csdn.net/knight_zhou/article/details/103683305
(2)也可以参阅我的 51cto订阅专栏: https://blog.51cto.com/cloumn/detail/99
官方文档
https://docs.ansible.com/ansible/2.7/dev_guide/index.html
实验环境
主机名 | OS | IP | 备注 |
vm201 | Centos7.7 | 172.20.128.31 | ansible2.7.8服务器 |
vm203 | Centos7.7 | 172.20.128.33 | 客户端 |
背景
有时候我们通过ansible执行shell或者playbook的时候,有时候是免密码登录客户端机器的。也就是说是通过密钥方式登录客户端机器,那么如何实现Python的 Ansible Api 2.x 的密钥方式了?
代码实现
在网上找了半天关于密钥方式的代码实现,很多人写代码写到一半,或者直接不全。或者直接贴核心代码,也没看见完整代码在哪里,乱七八糟的。所以本人摸索别人的代码以及结合官方文档。进行代码实现如下:
我们暂且命名为 ansible_api_key_shell.py 文件,用来实现密钥方式去执行shell命令
#!/usr/bin/python
#coding:utf-8
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from collections import namedtuple
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['/etc/ansible/hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)
Options = namedtuple ('Options',
['connection',
'remote_user',
'ask_sudo_pass',
'ack_pass',
'module_path',
'forks',
'become',
'become_method',
'become_user',
'check',
'listhosts',
'sudo_user',
'sudo',
'diff']
)
options = Options(connection='smart',
remote_user='www',
ack_pass=None,
sudo_user=None,
forks=5,
ask_sudo_pass=None,
module_path=None,
become=None,
become_method=None,
become_user=None,
listhosts=None,
check=False,
diff=False,
sudo=False)
play_source = dict(
name = 'exec shell',
#hosts = '10.20.128.21',
hosts = 'all',
gather_facts = 'yes',
tasks = [
dict(action=dict(module='shell', args='touch /tmp/xxzz')),
]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
## 定义任务队列
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
#passwords=dict(conn_pass="zhoulong")
passwords=None,
#private_key_file=key_file
)
##
result = tqm.run(play)
print(result)
我们执行一下脚本看看返回结果:
[www@vm201 ~]$ python ansible_api_key_shell.py
PLAY [exec shell] *********************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************
ok: [172.20.128.33]
TASK [shell] **************************************************************************************************************************************************
[WARNING]: Consider using the file module with state=touch rather than running 'touch'. If you need to use command because file is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [172.20.128.33]
0
然后我们在客户端看看是不是生成了文件:
[www@vm203 ~]$ ll /tmp/xxzz
-rw-rw-r-- 1 www www 0 Jul 1 23:57 /tmp/xxzz
到此执行成功。
至于如何执行playbook,这里就不再讲了,如果你读了我的另外一篇博文 "Ansible Api 2.x 详解" 或者我的51cto 博客专栏,你一定知道怎么写了。
需要注意的地方
之前我一直以为 定义任务队列的时候(TaskQueueManager) 需要把密钥文件指定位置,然后我通过查官方文档发现并没有这个参数。
所以如果我们在设置密码为空的前提下默认就会走密钥方式登录机器。这个是要注意的地方。