python 中的自定义 ansible 模块 - 如何解析相对角色文件路径?

Custom ansible module in python - How to resolve relative role file paths?

我正在 python 中编写一个新的自定义 ansible 模块。

我希望能够像 "file" 和 "copy" 模块在 "src" 中接收相对路径时一样解析我的代码中的路径(以便读取它们的内容)参数(路径相对于 root-dir/roles/x/files),例如。

可以吗?如果是,怎么做?

更新

目前这似乎是不可能的。我添加了功能请求 here.

DEFAULT_ROLES_PATHAnsible's constants.py 文件中定义:

DEFAULT_ROLES_PATH        = shell_expand_path(get_config(p, DEFAULTS, 'roles_path',       'ANSIBLE_ROLES_PATH',       '/etc/ansible/roles'))

通过导入它 from ansible.constant import DEFAULT_ROLES_PATH 您的模块将遵循 Ansible 项目中可能发生的任何路径更改。

utils.py 可能是您在编写模块时应该熟悉的下一个文件,因为它包含路径查找函数(参见 path_dwim)和其他特定于 Ansible 的交互函数。


如果您希望插件像 copy module, you can see the logic for the file pathing in the runner's __init__.py 那样工作:

if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:

    basedir = self.basedir
    if '_original_file' in inject:
        basedir = os.path.dirname(inject['_original_file'])
        filesdir = os.path.join(basedir, '..', 'files')
        if os.path.exists(filesdir):
            basedir = filesdir

其中 self.basedir 定义为 utils.default(basedir, lambda: os.getcwd()),其中 basedir 是可选的剧本目录。

通过为您的模块提供适当的 argument spec,您应该能够自动利用这些底层细节。

在您模块的底部,为您添加 basic module_utils to hook into methods expected to exist ('fail_json', etc) and populate other defaults

from ansible.module_utils.basic import *

我相信有了这些部分,您将触发文件搜索路径,但如果我不正确,请告诉我。

我把这个问题发到了 "ansible-devel" 群里,他们给了我一个方向,让我找到了答案。

您可以编写自定义动作插件并将其放在root-playbook-dir/action_plugins下。文件名必须是"your_mod_name.py"

代码应该是这样的:

#!/usr/bin/python

from ansible.runner.lookup_plugins.file import LookupModule as FilePlugin
from ansible import utils

class ActionModule(object):

    def __init__(self, runner):
        self.runner = runner

    def run(self, conn, tmp_path, module_name, module_args, inject, complex_args=None, **kwargs):

        options = {}
        options.update(utils.parse_kv(module_args))

        file_plugin = FilePlugin()
        files_content = file_plugin.run(terms=options.get('myarg'), inject=inject)
        options['myarg'] = files_content[0]

        return self.runner._execute_module(conn=conn, tmp="/tmp", module_name="mymod", args=utils.serialize_args(options), inject=inject)

代码使用 "file" 查找插件读取文件,然后执行自定义模块和 returns 其结果。

最终,您的自定义模块将在 "myarg" 参数中接收文件内容(而不是路径)。