问题描述
在创建自定义Python Ansible动作插件时遇到了以下问题:如何执行某些模块一次(我知道在YAML中可以设置run_once
和delegate_to
)?
例如,用户有以下代码:
from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleError
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
super(ActionModule, self).run(tmp, task_vars)
module_args = self._task.args.copy()
ret = {}
# create group
module_return = self._execute_module(module_name='group', module_args={'state':'present', 'name': 'bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
module_return = self._execute_module(module_name='user', module_args={'state':'present', 'name': 'bob', 'group': 'bob', 'home':'/nfs/bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
# run once this command ????
module_return = self._execute_module(module_name='file', module_args={'path':'/nfs/bob', 'state':'directory', 'mode': '0700'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
return ret
当前代码会为每个主机执行文件模块,但我需要执行该部分一次。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
在Ansible中,可以使用run_once
关键字来确保某些模块只执行一次。你可以将这个关键字添加到你的任务中,以确保它只在第一个主机上执行。
以下是如何修改你的代码来实现这一点的步骤:
1. 在你的任务中添加run_once: true
。
2. 将任务添加到你的动作插件中。
下面是修改后的代码示例:
from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleError
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
super(ActionModule, self).run(tmp, task_vars)
module_args = self._task.args.copy()
ret = {}
# create group
module_return = self._execute_module(module_name='group', module_args={'state':'present', 'name': 'bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
module_return = self._execute_module(module_name='user', module_args={'state':'present', 'name': 'bob', 'group': 'bob', 'home':'/nfs/bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
# run once this command ????
module_return = self._execute_module(module_name='file', module_args={'path':'/nfs/bob', 'state':'directory', 'mode': '0700', 'run_once': True}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
return ret
在上面的示例中,我们在file
模块的module_args
中添加了run_once: True
。这将确保该模块只在第一个主机上执行一次。
请注意,run_once
关键字只适用于当前任务,而不是整个动作插件。如果你有多个任务需要只执行一次,你需要在每个任务中添加run_once: true
。
方案2
如果你需要在整个动作插件中执行某些模块一次,你可以使用
delegate_to
关键字将任务委托给特定的主机。
另一种方法是使用delegate_to
关键字将任务委托给特定的主机,以确保它只在该主机上执行一次。
以下是如何修改你的代码来实现这一点的步骤:
1. 在你的任务中添加delegate_to: your_host
,将your_host
替换为你想要执行任务的主机。
2. 将任务添加到你的动作插件中。
下面是修改后的代码示例:
from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleError
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
super(ActionModule, self).run(tmp, task_vars)
module_args = self._task.args.copy()
ret = {}
# create group
module_return = self._execute_module(module_name='group', module_args={'state':'present', 'name': 'bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
module_return = self._execute_module(module_name='user', module_args={'state':'present', 'name': 'bob', 'group': 'bob', 'home':'/nfs/bob'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
# run once this command ????
module_return = self._execute_module(module_name='file', module_args={'path':'/nfs/bob', 'state':'directory', 'mode': '0700', 'delegate_to': 'your_host'}, task_vars=task_vars, tmp=tmp)
ret.update(module_return)
return ret
在上面的示例中,我们在file
模块的module_args
中添加了delegate_to: your_host
。这将确保该模块只在your_host
主机上执行一次。
请注意,delegate_to
关键字只适用于当前任务,而不是整个动作插件。如果你有多个任务需要只执行一次,你需要在每个任务中添加delegate_to: your_host
。
总结
在Ansible自定义动作插件中,你可以使用run_once
关键字或delegate_to
关键字来确保某些模块只执行一次。run_once
关键字适用于当前任务,而delegate_to
关键字可以将任务委托给特定的主机。根据你的需求选择适合的解决方案。