Ansible自定义动作插件中如何执行某些模块一次

64次阅读
没有评论

问题描述

在创建自定义Python Ansible动作插件时遇到了以下问题:如何执行某些模块一次(我知道在YAML中可以设置run_oncedelegate_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关键字可以将任务委托给特定的主机。根据你的需求选择适合的解决方案。

正文完